mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-06-11 08:14:43 +08:00
Sync: commaai/openpilot:master → sunnypilot/sunnypilot:master (#1749)
This commit is contained in:
101
.github/workflows/ci_weekly_report.yaml
vendored
101
.github/workflows/ci_weekly_report.yaml
vendored
@@ -1,101 +0,0 @@
|
||||
name: weekly CI test report
|
||||
on:
|
||||
schedule:
|
||||
- cron: '37 9 * * 1' # 9:37AM UTC -> 2:37AM PST every monday
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ci_runs:
|
||||
description: 'The amount of runs to trigger in CI test report'
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
CI_RUNS: ${{ github.event.inputs.ci_runs || '50' }}
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
if: github.repository == 'sunnypilot/sunnypilot'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
ci_runs: ${{ steps.ci_runs_setup.outputs.matrix }}
|
||||
steps:
|
||||
- id: ci_runs_setup
|
||||
name: CI_RUNS=${{ env.CI_RUNS }}
|
||||
run: |
|
||||
matrix=$(python3 -c "import json; print(json.dumps({ 'run_number' : list(range(${{ env.CI_RUNS }})) }))")
|
||||
echo "matrix=$matrix" >> $GITHUB_OUTPUT
|
||||
|
||||
ci_matrix_run:
|
||||
needs: [ setup ]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{fromJSON(needs.setup.outputs.ci_runs)}}
|
||||
uses: sunnypilot/sunnypilot/.github/workflows/ci_weekly_run.yaml@master
|
||||
with:
|
||||
run_number: ${{ matrix.run_number }}
|
||||
|
||||
report:
|
||||
needs: [ci_matrix_run]
|
||||
runs-on: ubuntu-latest
|
||||
if: always() && github.repository == 'commaai/openpilot'
|
||||
steps:
|
||||
- name: Get job results
|
||||
uses: actions/github-script@v8
|
||||
id: get-job-results
|
||||
with:
|
||||
script: |
|
||||
const jobs = await github
|
||||
.paginate("GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt}/jobs", {
|
||||
owner: "commaai",
|
||||
repo: "${{ github.event.repository.name }}",
|
||||
run_id: "${{ github.run_id }}",
|
||||
attempt: "${{ github.run_attempt }}",
|
||||
})
|
||||
var report = {}
|
||||
jobs.slice(1, jobs.length-1).forEach(job => {
|
||||
if (job.conclusion === "skipped") return;
|
||||
const jobName = job.name.split(" / ")[2];
|
||||
const runRegex = /\((.*?)\)/;
|
||||
const run = job.name.match(runRegex)[1];
|
||||
report[jobName] = report[jobName] || { successes: [], failures: [], canceled: [] };
|
||||
switch (job.conclusion) {
|
||||
case "success":
|
||||
report[jobName].successes.push({ "run_number": run, "link": job.html_url}); break;
|
||||
case "failure":
|
||||
report[jobName].failures.push({ "run_number": run, "link": job.html_url }); break;
|
||||
case "canceled":
|
||||
report[jobName].canceled.push({ "run_number": run, "link": job.html_url }); break;
|
||||
}
|
||||
});
|
||||
return JSON.stringify({"jobs": report});
|
||||
|
||||
- name: Add job results to summary
|
||||
env:
|
||||
JOB_RESULTS: ${{ fromJSON(steps.get-job-results.outputs.result) }}
|
||||
run: |
|
||||
cat <<EOF >> template.html
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Job</th>
|
||||
<th>✅ Passing</th>
|
||||
<th>❌ Failure Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for key in jobs.keys() %}<tr>
|
||||
<td>{% for i in range(5) %}{% if i+1 <= (5 * jobs[key]["successes"]|length // ${{ env.CI_RUNS }}) %}🟩{% else %}🟥{% endif %}{% endfor%}</td>
|
||||
<td>{{ key }}</td>
|
||||
<td>{{ 100 * jobs[key]["successes"]|length // ${{ env.CI_RUNS }} }}%</td>
|
||||
<td>{% if jobs[key]["failures"]|length > 0 %}<details>{% for failure in jobs[key]["failures"] %}<a href="{{ failure['link'] }}">Log for run #{{ failure['run_number'] }}</a><br>{% endfor %}</details>{% else %}{% endif %}</td>
|
||||
</td>
|
||||
</tr>{% endfor %}
|
||||
</table>
|
||||
EOF
|
||||
|
||||
pip install jinja2-cli
|
||||
echo $JOB_RESULTS | jinja2 template.html > report.html
|
||||
echo "# CI Test Report - ${{ env.CI_RUNS }} Runs" >> $GITHUB_STEP_SUMMARY
|
||||
cat report.html >> $GITHUB_STEP_SUMMARY
|
||||
17
.github/workflows/ci_weekly_run.yaml
vendored
17
.github/workflows/ci_weekly_run.yaml
vendored
@@ -1,17 +0,0 @@
|
||||
name: weekly CI test run
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
run_number:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
concurrency:
|
||||
group: ci-run-${{ inputs.run_number }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
uses: sunnypilot/sunnypilot/.github/workflows/tests.yaml@master
|
||||
with:
|
||||
run_number: ${{ inputs.run_number }}
|
||||
8
.github/workflows/tests.yaml
vendored
8
.github/workflows/tests.yaml
vendored
@@ -19,6 +19,8 @@ concurrency:
|
||||
|
||||
env:
|
||||
CI: 1
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
PYTEST: pytest --continue-on-collection-errors --durations=0 -n logical
|
||||
|
||||
jobs:
|
||||
build_release:
|
||||
@@ -127,8 +129,8 @@ jobs:
|
||||
run: |
|
||||
source selfdrive/test/setup_xvfb.sh
|
||||
# Pre-compile Python bytecode so each pytest worker doesn't need to
|
||||
pytest --collect-only -m 'not slow' -qq
|
||||
MAX_EXAMPLES=1 pytest -m 'not slow'
|
||||
$PYTEST --collect-only -m 'not slow' -qq
|
||||
MAX_EXAMPLES=1 $PYTEST -m 'not slow'
|
||||
|
||||
process_replay:
|
||||
name: process replay
|
||||
@@ -185,7 +187,7 @@ jobs:
|
||||
timeout-minutes: 4
|
||||
env:
|
||||
ONNXCPU: 1
|
||||
run: pytest selfdrive/test/process_replay/test_regen.py
|
||||
run: $PYTEST selfdrive/test/process_replay/test_regen.py
|
||||
|
||||
simulator_driving:
|
||||
name: simulator driving
|
||||
|
||||
3
Jenkinsfile
vendored
3
Jenkinsfile
vendored
@@ -210,7 +210,6 @@ node {
|
||||
'HW + Unit Tests': {
|
||||
deviceStage("tizi-hardware", "tizi-common", ["UNSAFE=1"], [
|
||||
step("build", "cd system/manager && ./build.py"),
|
||||
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py", [diffPaths: ["panda", "selfdrive/pandad/"]]),
|
||||
step("test power draw", "pytest -s system/hardware/tici/tests/test_power_draw.py"),
|
||||
step("test encoder", "LD_LIBRARY_PATH=/usr/local/lib pytest system/loggerd/tests/test_encoder.py", [diffPaths: ["system/loggerd/"]]),
|
||||
step("test manager", "pytest system/manager/test/test_manager.py"),
|
||||
@@ -219,12 +218,14 @@ node {
|
||||
'camerad OX03C10': {
|
||||
deviceStage("OX03C10", "tizi-ox03c10", ["UNSAFE=1"], [
|
||||
step("build", "cd system/manager && ./build.py"),
|
||||
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py", [diffPaths: ["panda", "selfdrive/pandad/"]]),
|
||||
step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 90]),
|
||||
])
|
||||
},
|
||||
'camerad OS04C10': {
|
||||
deviceStage("OS04C10", "tici-os04c10", ["UNSAFE=1"], [
|
||||
step("build", "cd system/manager && ./build.py"),
|
||||
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py", [diffPaths: ["panda", "selfdrive/pandad/"]]),
|
||||
step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 90]),
|
||||
])
|
||||
},
|
||||
|
||||
@@ -44,12 +44,13 @@ if arch != "larch64":
|
||||
import eigen
|
||||
import ffmpeg as ffmpeg_pkg
|
||||
import libjpeg
|
||||
import libyuv
|
||||
import ncurses
|
||||
import openssl3
|
||||
import python3_dev
|
||||
import zeromq
|
||||
import zstd
|
||||
pkgs = [bzip2, capnproto, eigen, ffmpeg_pkg, libjpeg, ncurses, openssl3, zeromq, zstd]
|
||||
pkgs = [bzip2, capnproto, eigen, ffmpeg_pkg, libjpeg, libyuv, ncurses, openssl3, zeromq, zstd]
|
||||
py_include = python3_dev.INCLUDE_DIR
|
||||
else:
|
||||
# TODO: remove when AGNOS has our new vendor pkgs
|
||||
@@ -89,7 +90,6 @@ env = Environment(
|
||||
"#third_party/acados/include/blasfeo/include",
|
||||
"#third_party/acados/include/hpipm/include",
|
||||
"#third_party/catch2/include",
|
||||
"#third_party/libyuv/include",
|
||||
[x.INCLUDE_DIR for x in pkgs],
|
||||
],
|
||||
LIBPATH=[
|
||||
@@ -98,7 +98,6 @@ env = Environment(
|
||||
"#third_party",
|
||||
"#selfdrive/pandad",
|
||||
"#rednose/helpers",
|
||||
f"#third_party/libyuv/{arch}/lib",
|
||||
f"#third_party/acados/{arch}/lib",
|
||||
[x.LIB_DIR for x in pkgs],
|
||||
],
|
||||
|
||||
@@ -499,7 +499,8 @@ struct DeviceState @0xa4d8b5af2aa492eb {
|
||||
pmicTempC @39 :List(Float32);
|
||||
intakeTempC @46 :Float32;
|
||||
exhaustTempC @47 :Float32;
|
||||
caseTempC @48 :Float32;
|
||||
gnssTempC @48 :Float32;
|
||||
bottomSocTempC @50 :Float32;
|
||||
maxTempC @44 :Float32; # max of other temps, used to control fan
|
||||
thermalZones @38 :List(ThermalZone);
|
||||
thermalStatus @14 :ThermalStatus;
|
||||
|
||||
2
panda
2
panda
Submodule panda updated: a4e30942fa...f5f296c65c
@@ -31,6 +31,7 @@ dependencies = [
|
||||
"eigen @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=eigen",
|
||||
"ffmpeg @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=ffmpeg",
|
||||
"libjpeg @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=libjpeg",
|
||||
"libyuv @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=libyuv",
|
||||
"openssl3 @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=openssl3",
|
||||
"python3-dev @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=python3-dev",
|
||||
"zstd @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=zstd",
|
||||
@@ -125,7 +126,7 @@ allow-direct-references = true
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
minversion = "6.0"
|
||||
addopts = "--ignore=openpilot/ --ignore=opendbc/ --ignore=panda/ --ignore=rednose_repo/ --ignore=tinygrad_repo/ --ignore=teleoprtc_repo/ --ignore=msgq/ -Werror --strict-config --strict-markers --durations=20 --maxprocesses=8 -n auto --dist=loadgroup"
|
||||
addopts = "--ignore=openpilot/ --ignore=opendbc/ --ignore=panda/ --ignore=rednose_repo/ --ignore=tinygrad_repo/ --ignore=teleoprtc_repo/ --ignore=msgq/ -Werror --strict-config --strict-markers --durations=10 -n auto --dist=loadgroup"
|
||||
cpp_files = "test_*"
|
||||
cpp_harness = "selfdrive/test/cpp_harness.py"
|
||||
python_files = "test_*.py"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
BIN
selfdrive/assets/icons_mici/setup/start_button.png
LFS
Normal file
BIN
selfdrive/assets/icons_mici/setup/start_button.png
LFS
Normal file
Binary file not shown.
BIN
selfdrive/assets/icons_mici/setup/start_button_pressed.png
LFS
Normal file
BIN
selfdrive/assets/icons_mici/setup/start_button_pressed.png
LFS
Normal file
Binary file not shown.
@@ -8,7 +8,7 @@ import numpy as np
|
||||
from openpilot.common.utils import tabulate
|
||||
from openpilot.tools.lib.logreader import LogReader
|
||||
|
||||
DEMO_ROUTE = "a2a0ccea32023010|2023-07-27--13-01-19"
|
||||
DEMO_ROUTE = "5beb9b58bd12b691/0000010a--a51155e496"
|
||||
MB = 1024 * 1024
|
||||
TABULATE_OPTS = dict(tablefmt="simple_grid", stralign="center", numalign="center")
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Import('env', 'arch', 'common')
|
||||
generator = File("#selfdrive/assets/fonts/process.py")
|
||||
source_files = Glob("#selfdrive/assets/fonts/*.ttf") + Glob("#selfdrive/assets/fonts/*.otf")
|
||||
output_files = [
|
||||
(f.abspath.split('.')[0] + ".fnt", f.abspath.split('.')[0] + ".png")
|
||||
(f"#{Path(f.path).with_suffix('.fnt')}", f"#{Path(f.path).with_suffix('.png')}")
|
||||
for f in source_files
|
||||
if "NotoColor" not in f.name
|
||||
]
|
||||
|
||||
@@ -30,7 +30,7 @@ const std::string VALID_CACHE_PATH = "/data/.openpilot_cache";
|
||||
|
||||
#define TMP_INSTALL_PATH "/data/tmppilot"
|
||||
|
||||
const int FONT_SIZE = 120;
|
||||
const int FONT_SIZE = 160;
|
||||
|
||||
extern const uint8_t str_continue[] asm("_binary_selfdrive_ui_installer_continue_openpilot_sh_start");
|
||||
extern const uint8_t str_continue_end[] asm("_binary_selfdrive_ui_installer_continue_openpilot_sh_end");
|
||||
@@ -88,7 +88,7 @@ void finishInstall() {
|
||||
int text_width = MeasureText(m, FONT_SIZE);
|
||||
DrawTextEx(font_display, m, (Vector2){(float)(GetScreenWidth() - text_width)/2 + FONT_SIZE, (float)(GetScreenHeight() - FONT_SIZE)/2}, FONT_SIZE, 0, WHITE);
|
||||
} else {
|
||||
DrawTextEx(font_display, "finishing setup", (Vector2){8, 10}, 82, 0, WHITE);
|
||||
DrawTextEx(font_display, "finishing setup", (Vector2){12, 0}, 77, 0, (Color){255, 255, 255, (unsigned char)(255 * 0.9)});
|
||||
}
|
||||
EndDrawing();
|
||||
util::sleep_for(60 * 1000);
|
||||
@@ -106,10 +106,10 @@ void renderProgress(int progress) {
|
||||
DrawRectangleRec(bar, (Color){70, 91, 234, 255});
|
||||
DrawTextEx(font_inter, (std::to_string(progress) + "%").c_str(), (Vector2){150, 670}, 85, 0, WHITE);
|
||||
} else {
|
||||
DrawTextEx(font_display, "installing", (Vector2){8, 10}, 82, 0, WHITE);
|
||||
DrawTextEx(font_display, "installing...", (Vector2){12, 0}, 77, 0, (Color){255, 255, 255, (unsigned char)(255 * 0.9)});
|
||||
const std::string percent_str = std::to_string(progress) + "%";
|
||||
DrawTextEx(font_roman, percent_str.c_str(), (Vector2){6, (float)(GetScreenHeight() - 128 + 18)}, 128, 0,
|
||||
(Color){255, 255, 255, (unsigned char)(255 * 0.9 * 0.35)});
|
||||
DrawTextEx(font_inter, percent_str.c_str(), (Vector2){12, (float)(GetScreenHeight() - 154 + 20)}, 154, 0,
|
||||
(Color){255, 255, 255, (unsigned char)(255 * 0.9 * 0.65)});
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import datetime
|
||||
import time
|
||||
|
||||
from cereal import log
|
||||
@@ -149,17 +150,22 @@ class MiciHomeLayout(Widget):
|
||||
self._did_long_press = False
|
||||
|
||||
def _get_version_text(self) -> tuple[str, str, str, str] | None:
|
||||
description = ui_state.params.get("UpdaterCurrentDescription")
|
||||
version = ui_state.params.get("Version")
|
||||
branch = ui_state.params.get("GitBranch")
|
||||
commit = ui_state.params.get("GitCommit")
|
||||
|
||||
if description is not None and len(description) > 0:
|
||||
# Expect "version / branch / commit / date"; be tolerant of other formats
|
||||
try:
|
||||
version, branch, commit, date = description.split(" / ")
|
||||
return version, branch, commit, date
|
||||
except Exception:
|
||||
return None
|
||||
if not all((version, branch, commit)):
|
||||
return None
|
||||
|
||||
return None
|
||||
commit_date_raw = ui_state.params.get("GitCommitDate")
|
||||
try:
|
||||
# GitCommitDate format from get_commit_date(): '%ct %ci' e.g. "'1708012345 2024-02-15 ...'"
|
||||
unix_ts = int(commit_date_raw.strip("'").split()[0])
|
||||
date_str = datetime.datetime.fromtimestamp(unix_ts).strftime("%b %d")
|
||||
except (ValueError, IndexError, TypeError, AttributeError):
|
||||
date_str = ""
|
||||
|
||||
return version, branch, commit[:7], date_str
|
||||
|
||||
def _render(self, _):
|
||||
# TODO: why is there extra space here to get it to be flush?
|
||||
|
||||
@@ -52,6 +52,7 @@ class MiciMainLayout(Scroller):
|
||||
# Set callbacks
|
||||
self._setup_callbacks()
|
||||
|
||||
gui_app.add_nav_stack_tick(self._handle_transitions)
|
||||
gui_app.push_widget(self)
|
||||
|
||||
# Start onboarding if terms or training not completed, make sure to push after self
|
||||
@@ -79,8 +80,6 @@ class MiciMainLayout(Scroller):
|
||||
# Render
|
||||
super()._render(self._rect)
|
||||
|
||||
self._handle_transitions()
|
||||
|
||||
def _handle_transitions(self):
|
||||
# Don't pop if onboarding
|
||||
if gui_app.get_active_widget() == self._onboarding_window:
|
||||
@@ -96,16 +95,15 @@ class MiciMainLayout(Scroller):
|
||||
else:
|
||||
self._scroll_to(self._home_layout)
|
||||
|
||||
# FIXME: these two pops can interrupt user interacting in the settings
|
||||
if self._onroad_time_delay is not None and rl.get_time() - self._onroad_time_delay >= ONROAD_DELAY:
|
||||
gui_app.pop_widgets_to(self)
|
||||
self._scroll_to(self._onroad_layout)
|
||||
gui_app.pop_widgets_to(self, lambda: self._scroll_to(self._onroad_layout))
|
||||
self._onroad_time_delay = None
|
||||
|
||||
# When car leaves standstill, pop nav stack and scroll to onroad
|
||||
CS = ui_state.sm["carState"]
|
||||
if not CS.standstill and self._prev_standstill:
|
||||
gui_app.pop_widgets_to(self)
|
||||
self._scroll_to(self._onroad_layout)
|
||||
gui_app.pop_widgets_to(self, lambda: self._scroll_to(self._onroad_layout))
|
||||
self._prev_standstill = CS.standstill
|
||||
|
||||
def _on_interactive_timeout(self):
|
||||
@@ -116,10 +114,10 @@ class MiciMainLayout(Scroller):
|
||||
if ui_state.started:
|
||||
# Don't pop if at standstill
|
||||
if not ui_state.sm["carState"].standstill:
|
||||
gui_app.pop_widgets_to(self)
|
||||
self._scroll_to(self._onroad_layout)
|
||||
gui_app.pop_widgets_to(self, lambda: self._scroll_to(self._onroad_layout))
|
||||
else:
|
||||
gui_app.pop_widgets_to(self)
|
||||
# Screen turns off on timeout offroad, so pop immediately without animation
|
||||
gui_app.pop_widgets_to(self, instant=True)
|
||||
self._scroll_to(self._home_layout)
|
||||
|
||||
def _on_bookmark_clicked(self):
|
||||
|
||||
@@ -8,14 +8,13 @@ from openpilot.common.filter_simple import FirstOrderFilter
|
||||
from openpilot.system.hardware import HARDWARE
|
||||
from openpilot.system.ui.lib.application import FontWeight, gui_app
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.nav_widget import NavWidget
|
||||
from openpilot.system.ui.widgets.button import SmallButton, SmallCircleIconButton
|
||||
from openpilot.system.ui.widgets.label import UnifiedLabel
|
||||
from openpilot.system.ui.widgets.slider import SmallSlider
|
||||
from openpilot.system.ui.mici_setup import TermsHeader, TermsPage as SetupTermsPage
|
||||
from openpilot.selfdrive.ui.ui_state import ui_state, device
|
||||
from openpilot.selfdrive.ui.mici.onroad.driver_state import DriverStateRenderer
|
||||
from openpilot.selfdrive.ui.mici.onroad.driver_camera_dialog import DriverCameraDialog
|
||||
from openpilot.selfdrive.ui.mici.onroad.driver_camera_dialog import BaseDriverCameraDialog
|
||||
from openpilot.system.ui.widgets.label import gui_label
|
||||
from openpilot.system.ui.lib.multilang import tr
|
||||
from openpilot.system.version import terms_version, training_version, terms_version_sp
|
||||
@@ -30,9 +29,9 @@ class OnboardingState(IntEnum):
|
||||
SUNNYLINK_CONSENT = 3
|
||||
|
||||
|
||||
class DriverCameraSetupDialog(DriverCameraDialog):
|
||||
class DriverCameraSetupDialog(BaseDriverCameraDialog):
|
||||
def __init__(self):
|
||||
super().__init__(no_escape=True)
|
||||
super().__init__()
|
||||
self.driver_state_renderer = DriverStateRenderer(inset=True)
|
||||
self.driver_state_renderer.set_rect(rl.Rectangle(0, 0, 120, 120))
|
||||
self.driver_state_renderer.load_icons()
|
||||
@@ -441,11 +440,9 @@ class TermsPage(SetupTermsPage):
|
||||
))
|
||||
|
||||
|
||||
class OnboardingWindow(NavWidget):
|
||||
class OnboardingWindow(Widget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.set_back_enabled(False)
|
||||
|
||||
self._accepted_terms: bool = ui_state.params.get("HasAcceptedTerms") == terms_version
|
||||
self._training_done: bool = ui_state.params.get("CompletedTrainingVersion") == training_version
|
||||
|
||||
@@ -507,6 +504,7 @@ class OnboardingWindow(NavWidget):
|
||||
self.close()
|
||||
|
||||
def _render(self, _):
|
||||
rl.draw_rectangle_rec(self._rect, rl.BLACK)
|
||||
if self._state == OnboardingState.TERMS:
|
||||
self._terms.render(self._rect)
|
||||
elif self._state == OnboardingState.SUNNYLINK_CONSENT:
|
||||
|
||||
@@ -11,7 +11,6 @@ from openpilot.selfdrive.ui.widgets.ssh_key import SshKeyAction
|
||||
class DeveloperLayoutMici(NavScroller):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.set_back_callback(gui_app.pop_widget)
|
||||
|
||||
def github_username_callback(username: str):
|
||||
if username:
|
||||
|
||||
@@ -7,32 +7,25 @@ from collections.abc import Callable
|
||||
from openpilot.common.basedir import BASEDIR
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.common.time_helpers import system_time_valid
|
||||
from openpilot.system.ui.widgets.scroller import NavScroller
|
||||
from openpilot.system.ui.lib.scroll_panel2 import GuiScrollPanel2
|
||||
from openpilot.system.ui.widgets.scroller import NavRawScrollPanel, NavScroller
|
||||
from openpilot.selfdrive.ui.mici.widgets.button import BigButton, BigCircleButton
|
||||
from openpilot.selfdrive.ui.mici.widgets.dialog import BigDialog, BigConfirmationDialogV2
|
||||
from openpilot.selfdrive.ui.mici.widgets.pairing_dialog import PairingDialog
|
||||
from openpilot.selfdrive.ui.mici.onroad.driver_camera_dialog import DriverCameraDialog
|
||||
from openpilot.selfdrive.ui.mici.layouts.onboarding import TrainingGuide
|
||||
from openpilot.selfdrive.ui.mici.layouts.onboarding import TrainingGuide, TermsPage
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight, MousePos
|
||||
from openpilot.system.ui.lib.multilang import tr
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.nav_widget import NavWidget
|
||||
from openpilot.selfdrive.ui.ui_state import ui_state
|
||||
from openpilot.system.ui.widgets.label import MiciLabel
|
||||
from openpilot.system.ui.widgets.html_render import HtmlModal, HtmlRenderer
|
||||
from openpilot.system.athena.registration import UNREGISTERED_DONGLE_ID
|
||||
|
||||
|
||||
class MiciFccModal(NavWidget):
|
||||
BACK_TOUCH_AREA_PERCENTAGE = 0.1
|
||||
|
||||
class MiciFccModal(NavRawScrollPanel):
|
||||
def __init__(self, file_path: str | None = None, text: str | None = None):
|
||||
super().__init__()
|
||||
self.set_back_callback(gui_app.pop_widget)
|
||||
self._content = HtmlRenderer(file_path=file_path, text=text)
|
||||
self._scroll_panel = GuiScrollPanel2(horizontal=False)
|
||||
self._scroll_panel.set_enabled(lambda: self.enabled and not self._swiping_away)
|
||||
self._fcc_logo = gui_app.texture("icons_mici/settings/device/fcc_logo.png", 76, 64)
|
||||
|
||||
def _render(self, rect: rl.Rectangle):
|
||||
@@ -124,6 +117,8 @@ class PairBigButton(BigButton):
|
||||
return 64
|
||||
|
||||
def _update_state(self):
|
||||
super()._update_state()
|
||||
|
||||
if ui_state.prime_state.is_paired():
|
||||
self.set_text("paired")
|
||||
if ui_state.prime_state.is_prime():
|
||||
@@ -171,6 +166,8 @@ class UpdateOpenpilotBigButton(BigButton):
|
||||
self.set_enabled(True)
|
||||
|
||||
def _handle_mouse_release(self, mouse_pos: MousePos):
|
||||
super()._handle_mouse_release(mouse_pos)
|
||||
|
||||
if not system_time_valid():
|
||||
dlg = BigDialog(tr("Please connect to Wi-Fi to update"), "")
|
||||
gui_app.push_widget(dlg)
|
||||
@@ -198,6 +195,8 @@ class UpdateOpenpilotBigButton(BigButton):
|
||||
self.set_text("update sunnypilot")
|
||||
|
||||
def _update_state(self):
|
||||
super()._update_state()
|
||||
|
||||
if ui_state.started:
|
||||
self.set_enabled(False)
|
||||
return
|
||||
@@ -302,6 +301,7 @@ class DeviceLayoutMici(NavScroller):
|
||||
|
||||
self._power_off_btn = BigCircleButton("icons_mici/settings/device/power.png", red=True, icon_size=(64, 66))
|
||||
self._power_off_btn.set_click_callback(lambda: _engaged_confirmation_callback(power_off_callback, "power off"))
|
||||
self._power_off_btn.set_visible(lambda: not ui_state.ignition)
|
||||
|
||||
regulatory_btn = BigButton("regulatory info", "", "icons_mici/settings/device/info.png")
|
||||
regulatory_btn.set_click_callback(self._on_regulatory)
|
||||
@@ -314,30 +314,25 @@ class DeviceLayoutMici(NavScroller):
|
||||
review_training_guide_btn.set_click_callback(lambda: gui_app.push_widget(TrainingGuide(completed_callback=gui_app.pop_widget)))
|
||||
review_training_guide_btn.set_enabled(lambda: ui_state.is_offroad())
|
||||
|
||||
terms_btn = BigButton("terms &\nconditions", "", "icons_mici/settings/device/info.png")
|
||||
terms_btn.set_click_callback(lambda: gui_app.push_widget(TermsPage(on_accept=gui_app.pop_widget)))
|
||||
terms_btn.set_enabled(lambda: ui_state.is_offroad())
|
||||
|
||||
self._scroller.add_widgets([
|
||||
DeviceInfoLayoutMici(),
|
||||
UpdateOpenpilotBigButton(),
|
||||
PairBigButton(),
|
||||
review_training_guide_btn,
|
||||
driver_cam_btn,
|
||||
terms_btn,
|
||||
regulatory_btn,
|
||||
reset_calibration_btn,
|
||||
uninstall_openpilot_btn,
|
||||
regulatory_btn,
|
||||
reboot_btn,
|
||||
self._power_off_btn,
|
||||
])
|
||||
|
||||
# Set up back navigation
|
||||
# TODO: can this somehow be generic in widgets/__init__.py or application.py?
|
||||
self.set_back_callback(gui_app.pop_widget)
|
||||
|
||||
# Hide power off button when onroad
|
||||
ui_state.add_offroad_transition_callback(self._offroad_transition)
|
||||
|
||||
def _on_regulatory(self):
|
||||
if not self._fcc_dialog:
|
||||
self._fcc_dialog = MiciFccModal(os.path.join(BASEDIR, "selfdrive/assets/offroad/mici_fcc.html"))
|
||||
gui_app.push_widget(self._fcc_dialog)
|
||||
|
||||
def _offroad_transition(self):
|
||||
self._power_off_btn.set_visible(ui_state.is_offroad())
|
||||
|
||||
@@ -14,7 +14,7 @@ from openpilot.system.ui.lib.wrap_text import wrap_text
|
||||
from openpilot.system.ui.lib.scroll_panel2 import GuiScrollPanel2
|
||||
from openpilot.system.ui.lib.multilang import tr, trn, tr_noop
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.nav_widget import NavWidget
|
||||
from openpilot.system.ui.widgets.scroller import NavRawScrollPanel
|
||||
|
||||
TITLE = tr_noop("Firehose Mode")
|
||||
DESCRIPTION = tr_noop(
|
||||
@@ -218,10 +218,5 @@ class FirehoseLayoutBase(Widget):
|
||||
time.sleep(self.UPDATE_INTERVAL)
|
||||
|
||||
|
||||
class FirehoseLayout(FirehoseLayoutBase, NavWidget):
|
||||
BACK_TOUCH_AREA_PERCENTAGE = 0.1
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.set_back_callback(gui_app.pop_widget)
|
||||
self._scroll_panel.set_enabled(lambda: self.enabled and not self._swiping_away)
|
||||
class FirehoseLayout(NavRawScrollPanel, FirehoseLayoutBase):
|
||||
pass
|
||||
|
||||
@@ -148,9 +148,6 @@ class NetworkLayoutMici(NavScroller):
|
||||
metered = ui_state.params.get_bool("GsmMetered")
|
||||
self._wifi_manager.update_gsm_settings(roaming_enabled, ui_state.params.get("GsmApn") or "", metered)
|
||||
|
||||
# Set up back navigation
|
||||
self.set_back_callback(gui_app.pop_widget)
|
||||
|
||||
def _update_state(self):
|
||||
super()._update_state()
|
||||
|
||||
@@ -166,13 +163,13 @@ class NetworkLayoutMici(NavScroller):
|
||||
self._wifi_manager.set_active(True)
|
||||
|
||||
# Process wifi callbacks while at any point in the nav stack
|
||||
gui_app.set_nav_stack_tick(self._wifi_manager.process_callbacks)
|
||||
gui_app.add_nav_stack_tick(self._wifi_manager.process_callbacks)
|
||||
|
||||
def hide_event(self):
|
||||
super().hide_event()
|
||||
self._wifi_manager.set_active(False)
|
||||
|
||||
gui_app.set_nav_stack_tick(None)
|
||||
gui_app.remove_nav_stack_tick(self._wifi_manager.process_callbacks)
|
||||
|
||||
def _toggle_roaming(self, checked: bool):
|
||||
self._wifi_manager.update_gsm_settings(checked, ui_state.params.get("GsmApn") or "", ui_state.params.get_bool("GsmMetered"))
|
||||
|
||||
@@ -129,12 +129,10 @@ class WifiButton(BigButton):
|
||||
return
|
||||
|
||||
self._network_forgetting = True
|
||||
self._forget_btn.set_visible(False)
|
||||
self._wifi_manager.forget_connection(self._network.ssid)
|
||||
|
||||
def on_forgotten(self):
|
||||
self._network_forgetting = False
|
||||
self._forget_btn.set_visible(True)
|
||||
|
||||
def set_network_missing(self, missing: bool):
|
||||
self._network_missing = missing
|
||||
@@ -150,7 +148,7 @@ class WifiButton(BigButton):
|
||||
|
||||
@property
|
||||
def _show_forget_btn(self):
|
||||
if self._network.is_tethering:
|
||||
if self._network.is_tethering or self._network_forgetting:
|
||||
return False
|
||||
|
||||
return (self._is_saved and not self._wrong_password) or self._is_connecting
|
||||
@@ -217,6 +215,8 @@ class WifiButton(BigButton):
|
||||
return self._wifi_manager.connected_ssid == self._network.ssid
|
||||
|
||||
def _update_state(self):
|
||||
super()._update_state()
|
||||
|
||||
if any((self._network_missing, self._is_connecting, self._is_connected, self._network_forgetting,
|
||||
self._network.security_type == SecurityType.UNSUPPORTED)):
|
||||
self.set_enabled(False)
|
||||
@@ -274,9 +274,6 @@ class WifiUIMici(NavScroller):
|
||||
def __init__(self, wifi_manager: WifiManager):
|
||||
super().__init__()
|
||||
|
||||
# Set up back navigation
|
||||
self.set_back_callback(gui_app.pop_widget)
|
||||
|
||||
self._loading_animation = LoadingAnimation()
|
||||
|
||||
self._wifi_manager = wifi_manager
|
||||
|
||||
@@ -49,7 +49,4 @@ class SettingsLayout(NavScroller):
|
||||
developer_btn,
|
||||
])
|
||||
|
||||
# Set up back navigation
|
||||
self.set_back_callback(gui_app.pop_widget)
|
||||
|
||||
self._font_medium = gui_app.font(FontWeight.MEDIUM)
|
||||
|
||||
@@ -12,7 +12,6 @@ PERSONALITY_TO_INT = log.LongitudinalPersonality.schema.enumerants
|
||||
class TogglesLayoutMici(NavScroller):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.set_back_callback(gui_app.pop_widget)
|
||||
|
||||
self._personality_toggle = BigMultiParamToggle("driving personality", "LongitudinalPersonality", ["aggressive", "standard", "relaxed"])
|
||||
self._experimental_btn = BigParamControl("experimental mode", "ExperimentalMode")
|
||||
|
||||
@@ -14,7 +14,7 @@ from openpilot.selfdrive.ui.mici.onroad.cameraview import CameraView
|
||||
from openpilot.system.ui.lib.application import FontWeight, gui_app, MousePos, MouseEvent
|
||||
from openpilot.system.ui.widgets.label import UnifiedLabel
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.common.filter_simple import BounceFilter, FirstOrderFilter
|
||||
from openpilot.common.filter_simple import BounceFilter
|
||||
from openpilot.common.transformations.camera import DEVICE_CAMERAS, DeviceCameraConfig, view_frame_from_device_frame
|
||||
from openpilot.common.transformations.orientation import rot_from_euler
|
||||
from enum import IntEnum
|
||||
@@ -50,8 +50,6 @@ class BookmarkIcon(Widget):
|
||||
super().__init__()
|
||||
self._bookmark_callback = bookmark_callback
|
||||
self._icon = gui_app.texture("icons_mici/onroad/bookmark.png", 180, 180)
|
||||
self._icon_fill = gui_app.texture("icons_mici/onroad/bookmark_fill.png", 180, 180)
|
||||
self._active_icon = self._icon
|
||||
self._offset_filter = BounceFilter(0.0, 0.1, 1 / gui_app.target_fps)
|
||||
|
||||
# State
|
||||
@@ -90,7 +88,6 @@ class BookmarkIcon(Widget):
|
||||
|
||||
if self._offset_filter.x < 1e-3:
|
||||
self._interacting = False
|
||||
self._active_icon = self._icon
|
||||
|
||||
def _handle_mouse_event(self, mouse_event: MouseEvent):
|
||||
if not ui_state.started:
|
||||
@@ -103,7 +100,6 @@ class BookmarkIcon(Widget):
|
||||
self._is_swiping = True
|
||||
self._is_swiping_left = False
|
||||
self._state = BookmarkState.DRAGGING
|
||||
self._active_icon = self._icon
|
||||
|
||||
elif mouse_event.left_down and self._is_swiping:
|
||||
self._swipe_current_x = mouse_event.pos.x
|
||||
@@ -120,7 +116,6 @@ class BookmarkIcon(Widget):
|
||||
if swipe_distance > self.PEEK_THRESHOLD:
|
||||
self._state = BookmarkState.TRIGGERED
|
||||
self._triggered_time = rl.get_time()
|
||||
self._active_icon = self._icon_fill
|
||||
self._bookmark_callback()
|
||||
else:
|
||||
# Otherwise, transition back to hidden
|
||||
@@ -134,8 +129,8 @@ class BookmarkIcon(Widget):
|
||||
"""Render the bookmark icon."""
|
||||
if self._offset_filter.x > 0:
|
||||
icon_x = self.rect.x + self.rect.width - round(self._offset_filter.x)
|
||||
icon_y = self.rect.y + (self.rect.height - self._active_icon.height) / 2 # Vertically centered
|
||||
rl.draw_texture(self._active_icon, int(icon_x), int(icon_y), rl.WHITE)
|
||||
icon_y = self.rect.y + (self.rect.height - self._icon.height) / 2 # Vertically centered
|
||||
rl.draw_texture(self._icon, int(icon_x), int(icon_y), rl.WHITE)
|
||||
|
||||
|
||||
class AugmentedRoadView(CameraView):
|
||||
@@ -169,7 +164,6 @@ class AugmentedRoadView(CameraView):
|
||||
alignment_vertical=rl.GuiTextAlignmentVertical.TEXT_ALIGN_MIDDLE)
|
||||
|
||||
self._fade_texture = gui_app.texture("icons_mici/onroad/onroad_fade.png")
|
||||
self._fade_alpha_filter = FirstOrderFilter(0, 0.1, 1 / gui_app.target_fps)
|
||||
|
||||
# debug
|
||||
self._pm = messaging.PubMaster(['uiDebug'])
|
||||
@@ -222,11 +216,8 @@ class AugmentedRoadView(CameraView):
|
||||
# Draw all UI overlays
|
||||
self._model_renderer.render(self._content_rect)
|
||||
|
||||
# Fade out bottom of overlays for looks (only when engaged)
|
||||
fade_alpha = self._fade_alpha_filter.update(ui_state.status != UIStatus.DISENGAGED)
|
||||
if fade_alpha > 1e-2:
|
||||
rl.draw_texture_ex(self._fade_texture, rl.Vector2(self._content_rect.x, self._content_rect.y), 0.0, 1.0,
|
||||
rl.Color(255, 255, 255, int(255 * fade_alpha)))
|
||||
# Fade out bottom of overlays for looks
|
||||
rl.draw_texture_ex(self._fade_texture, rl.Vector2(self._content_rect.x, self._content_rect.y), 0.0, 1.0, rl.WHITE)
|
||||
|
||||
alert_to_render, not_animating_out = self._alert_renderer.will_render()
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ from openpilot.selfdrive.ui.ui_state import ui_state, device
|
||||
from openpilot.selfdrive.selfdrived.events import EVENTS, ET
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight
|
||||
from openpilot.system.ui.lib.multilang import tr
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.nav_widget import NavWidget
|
||||
from openpilot.system.ui.widgets.label import gui_label
|
||||
|
||||
@@ -24,19 +25,15 @@ class DriverCameraView(CameraView):
|
||||
return base
|
||||
|
||||
|
||||
class DriverCameraDialog(NavWidget):
|
||||
def __init__(self, no_escape=False):
|
||||
class BaseDriverCameraDialog(Widget):
|
||||
# Not a NavWidget so training guide can use this without back navigation
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._camera_view = DriverCameraView("camerad", VisionStreamType.VISION_STREAM_DRIVER)
|
||||
self.driver_state_renderer = DriverStateRenderer(lines=True)
|
||||
self.driver_state_renderer.set_rect(rl.Rectangle(0, 0, 200, 200))
|
||||
self.driver_state_renderer.load_icons()
|
||||
self._pm: messaging.PubMaster | None = None
|
||||
if not no_escape:
|
||||
# TODO: this can grow unbounded, should be given some thought
|
||||
device.add_interactive_timeout_callback(gui_app.pop_widget)
|
||||
self.set_back_callback(gui_app.pop_widget)
|
||||
self.set_back_enabled(not no_escape)
|
||||
|
||||
# Load eye icons
|
||||
self._eye_fill_texture = None
|
||||
@@ -231,6 +228,13 @@ class DriverCameraDialog(NavWidget):
|
||||
rl.draw_texture_v(self._glasses_texture, glasses_pos, rl.Color(70, 80, 161, int(255 * glasses_prob)))
|
||||
|
||||
|
||||
class DriverCameraDialog(NavWidget, BaseDriverCameraDialog):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
# TODO: this can grow unbounded, should be given some thought
|
||||
device.add_interactive_timeout_callback(gui_app.pop_widget)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
gui_app.init_window("Driver Camera View (mici)")
|
||||
|
||||
|
||||
@@ -38,10 +38,10 @@ KNOWN_LEAKS = {
|
||||
"openpilot.system.ui.widgets.label.Label",
|
||||
"openpilot.system.ui.widgets.button.Button",
|
||||
"openpilot.system.ui.widgets.html_render.HtmlRenderer",
|
||||
"openpilot.system.ui.widgets.NavBar",
|
||||
"openpilot.system.ui.widgets.nav_widget.NavBar",
|
||||
"openpilot.selfdrive.ui.mici.layouts.settings.device.MiciFccModal",
|
||||
"openpilot.system.ui.widgets.inputbox.InputBox",
|
||||
"openpilot.system.ui.widgets.scroller_tici.Scroller",
|
||||
"openpilot.system.ui.widgets.scroller.Scroller",
|
||||
"openpilot.system.ui.widgets.label.UnifiedLabel",
|
||||
"openpilot.system.ui.widgets.mici_keyboard.MiciKeyboard",
|
||||
"openpilot.selfdrive.ui.mici.widgets.dialog.BigConfirmationDialogV2",
|
||||
|
||||
@@ -36,6 +36,7 @@ class BigCircleButton(Widget):
|
||||
# State
|
||||
self.set_rect(rl.Rectangle(0, 0, 180, 180))
|
||||
self._scale_filter = BounceFilter(1.0, 0.1, 1 / gui_app.target_fps)
|
||||
self._click_delay = 0.075
|
||||
|
||||
# Icons
|
||||
self._txt_icon = gui_app.texture(icon, *icon_size)
|
||||
@@ -117,6 +118,7 @@ class BigButton(Widget):
|
||||
self.set_icon(icon)
|
||||
|
||||
self._scale_filter = BounceFilter(1.0, 0.1, 1 / gui_app.target_fps)
|
||||
self._click_delay = 0.075
|
||||
self._shake_start: float | None = None
|
||||
|
||||
self._rotate_icon_t: float | None = None
|
||||
|
||||
@@ -22,7 +22,6 @@ class BigDialogBase(NavWidget, abc.ABC):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.set_rect(rl.Rectangle(0, 0, gui_app.width, gui_app.height))
|
||||
self.set_back_callback(gui_app.pop_widget)
|
||||
|
||||
|
||||
class BigDialog(BigDialogBase):
|
||||
@@ -78,17 +77,17 @@ class BigConfirmationDialogV2(BigDialogBase):
|
||||
self._slider = RedBigSlider(title, icon_txt, confirm_callback=self._on_confirm)
|
||||
else:
|
||||
self._slider = BigSlider(title, icon_txt, confirm_callback=self._on_confirm)
|
||||
self._slider.set_enabled(lambda: self.enabled and not self._swiping_away) # self.enabled for nav stack
|
||||
self._slider.set_enabled(lambda: self.enabled and not self.is_dismissing) # for nav stack + NavWidget
|
||||
|
||||
def _on_confirm(self):
|
||||
if self._exit_on_confirm:
|
||||
gui_app.pop_widget()
|
||||
if self._confirm_callback:
|
||||
self.dismiss(self._confirm_callback)
|
||||
elif self._confirm_callback:
|
||||
self._confirm_callback()
|
||||
|
||||
def _update_state(self):
|
||||
super()._update_state()
|
||||
if self._swiping_away and not self._slider.confirmed:
|
||||
if self.is_dismissing and not self._slider.confirmed:
|
||||
self._slider.reset()
|
||||
|
||||
def _render(self, _):
|
||||
@@ -110,7 +109,7 @@ class BigInputDialog(BigDialogBase):
|
||||
font_weight=FontWeight.MEDIUM)
|
||||
self._keyboard = MiciKeyboard()
|
||||
self._keyboard.set_text(default_text)
|
||||
self._keyboard.set_enabled(lambda: self.enabled) # for nav stack
|
||||
self._keyboard.set_enabled(lambda: self.enabled and not self.is_dismissing) # for nav stack + NavWidget
|
||||
self._minimum_length = minimum_length
|
||||
|
||||
self._backspace_held_time: float | None = None
|
||||
@@ -128,14 +127,16 @@ class BigInputDialog(BigDialogBase):
|
||||
|
||||
def confirm_callback_wrapper():
|
||||
text = self._keyboard.text()
|
||||
gui_app.pop_widget()
|
||||
if confirm_callback:
|
||||
confirm_callback(text)
|
||||
self.dismiss((lambda: confirm_callback(text)) if confirm_callback else None)
|
||||
self._confirm_callback = confirm_callback_wrapper
|
||||
|
||||
def _update_state(self):
|
||||
super()._update_state()
|
||||
|
||||
if self.is_dismissing:
|
||||
self._backspace_held_time = None
|
||||
return
|
||||
|
||||
last_mouse_event = gui_app.last_mouse_event
|
||||
if last_mouse_event.left_down and rl.check_collision_point_rec(last_mouse_event.pos, self._top_right_button_rect) and self._backspace_img_alpha.x > 1:
|
||||
if self._backspace_held_time is None:
|
||||
@@ -230,6 +231,10 @@ class BigInputDialog(BigDialogBase):
|
||||
super()._handle_mouse_press(mouse_pos)
|
||||
# TODO: need to track where press was so enter and back can activate on release rather than press
|
||||
# or turn into icon widgets :eyes_open:
|
||||
|
||||
if self.is_dismissing:
|
||||
return
|
||||
|
||||
# handle backspace icon click
|
||||
if rl.check_collision_point_rec(mouse_pos, self._top_right_button_rect) and self._backspace_img_alpha.x > 254:
|
||||
self._keyboard.backspace()
|
||||
|
||||
@@ -19,7 +19,6 @@ class PairingDialog(NavWidget):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.set_back_callback(gui_app.pop_widget)
|
||||
self._params = Params()
|
||||
self._qr_texture: rl.Texture | None = None
|
||||
self._last_qr_generation = float("-inf")
|
||||
@@ -69,8 +68,8 @@ class PairingDialog(NavWidget):
|
||||
|
||||
def _update_state(self):
|
||||
super()._update_state()
|
||||
if ui_state.prime_state.is_paired():
|
||||
self._playing_dismiss_animation = True
|
||||
if ui_state.prime_state.is_paired() and not self.is_dismissing:
|
||||
self.dismiss()
|
||||
|
||||
def _render(self, rect: rl.Rectangle):
|
||||
self._check_qr_refresh()
|
||||
|
||||
@@ -23,11 +23,12 @@ MIN_VOLUME = 0.1
|
||||
SELFDRIVE_STATE_TIMEOUT = 5 # 5 seconds
|
||||
FILTER_DT = 1. / (micd.SAMPLE_RATE / micd.FFT_SAMPLES)
|
||||
|
||||
AMBIENT_DB = 30 # DB where MIN_VOLUME is applied
|
||||
AMBIENT_DB = 24 # DB where MIN_VOLUME is applied
|
||||
DB_SCALE = 30 # AMBIENT_DB + DB_SCALE is where MAX_VOLUME is applied
|
||||
|
||||
VOLUME_BASE = 20
|
||||
if HARDWARE.get_device_type() == "tizi":
|
||||
AMBIENT_DB = 30
|
||||
VOLUME_BASE = 10
|
||||
|
||||
AudibleAlert = car.CarControl.HUDControl.AudibleAlert
|
||||
|
||||
@@ -23,10 +23,17 @@ def setup_state():
|
||||
params.put("HasAcceptedTerms", terms_version)
|
||||
params.put("CompletedTrainingVersion", training_version)
|
||||
params.put("DongleId", "test123456789")
|
||||
# Combined description for layouts that still use it (BIG home, settings/software)
|
||||
params.put("UpdaterCurrentDescription", "0.10.1 / test-branch / abc1234 / Nov 30")
|
||||
params.put("HasAcceptedTermsSP", terms_version_sp)
|
||||
params.put("CompletedSunnylinkConsentVersion", sunnylink_consent_version)
|
||||
|
||||
# Params for mici home
|
||||
params.put("Version", "0.10.1")
|
||||
params.put("GitBranch", "test-branch")
|
||||
params.put("GitCommit", "abc12340ff9131237ba23a1d0fbd8edf9c80e87")
|
||||
params.put("GitCommitDate", "'1732924800 2024-11-30 00:00:00 +0000'")
|
||||
|
||||
|
||||
def run_replay(variant: LayoutVariant) -> None:
|
||||
if HEADLESS:
|
||||
|
||||
@@ -52,7 +52,8 @@ class ThermalConfig:
|
||||
memory: ThermalZone | None = None
|
||||
intake: ThermalZone | None = None
|
||||
exhaust: ThermalZone | None = None
|
||||
case: ThermalZone | None = None
|
||||
gnss: ThermalZone | None = None
|
||||
bottomSoc: ThermalZone | None = None
|
||||
|
||||
def get_msg(self):
|
||||
ret = {}
|
||||
|
||||
@@ -321,11 +321,12 @@ class Tici(HardwareBase):
|
||||
os.system("sudo poweroff")
|
||||
|
||||
def get_thermal_config(self):
|
||||
intake, exhaust, case = None, None, None
|
||||
intake, exhaust, gnss, bottomSoc = None, None, None, None
|
||||
if self.get_device_type() == "mici":
|
||||
case = ThermalZone("case")
|
||||
gnss = ThermalZone("gnss")
|
||||
intake = ThermalZone("intake")
|
||||
exhaust = ThermalZone("exhaust")
|
||||
bottomSoc = ThermalZone("bottom_soc")
|
||||
return ThermalConfig(cpu=[ThermalZone(f"cpu{i}-silver-usr") for i in range(4)] +
|
||||
[ThermalZone(f"cpu{i}-gold-usr") for i in range(4)],
|
||||
gpu=[ThermalZone("gpu0-usr"), ThermalZone("gpu1-usr")],
|
||||
@@ -334,7 +335,8 @@ class Tici(HardwareBase):
|
||||
pmic=[ThermalZone("pm8998_tz"), ThermalZone("pm8005_tz")],
|
||||
intake=intake,
|
||||
exhaust=exhaust,
|
||||
case=case)
|
||||
gnss=gnss,
|
||||
bottomSoc=bottomSoc)
|
||||
|
||||
def set_display_power(self, on):
|
||||
try:
|
||||
|
||||
@@ -2,11 +2,12 @@ Import('env', 'arch', 'messaging', 'common', 'visionipc')
|
||||
|
||||
libs = [common, messaging, visionipc,
|
||||
'avformat', 'avcodec', 'swresample', 'avutil', 'x264',
|
||||
'yuv', 'pthread', 'z', 'm', 'zstd']
|
||||
'pthread', 'z', 'm', 'zstd']
|
||||
|
||||
src = ['logger.cc', 'zstd_writer.cc', 'video_writer.cc', 'encoder/encoder.cc', 'encoder/v4l_encoder.cc', 'encoder/jpeg_encoder.cc']
|
||||
if arch != "larch64":
|
||||
src += ['encoder/ffmpeg_encoder.cc']
|
||||
libs += ['yuv']
|
||||
|
||||
if arch == "Darwin":
|
||||
# exclude v4l
|
||||
@@ -20,4 +21,4 @@ env.Program('encoderd', ['encoderd.cc'], LIBS=libs + ["jpeg"])
|
||||
env.Program('bootlog.cc', LIBS=libs)
|
||||
|
||||
if GetOption('extras'):
|
||||
env.Program('tests/test_logger', ['tests/test_runner.cc', 'tests/test_logger.cc', 'tests/test_zstd_writer.cc'], LIBS=libs + ['curl', 'crypto'])
|
||||
env.Program('tests/test_logger', ['tests/test_runner.cc', 'tests/test_logger.cc', 'tests/test_zstd_writer.cc'], LIBS=libs)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
|
||||
#include "third_party/libyuv/include/libyuv.h"
|
||||
#include "libyuv.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "common/util.h"
|
||||
#include "common/timing.h"
|
||||
|
||||
#include "third_party/libyuv/include/libyuv.h"
|
||||
#include "third_party/linux/include/msm_media_info.h"
|
||||
|
||||
// has to be in this order
|
||||
|
||||
@@ -223,7 +223,7 @@ class GuiApplication(GuiApplicationExt):
|
||||
self._frame = 0
|
||||
self._window_close_requested = False
|
||||
self._nav_stack: list[object] = []
|
||||
self._nav_stack_tick: Callable[[], None] | None = None
|
||||
self._nav_stack_ticks: list[Callable[[], None]] = []
|
||||
self._nav_stack_widgets_to_render = 1 if self.big_ui() else 2
|
||||
|
||||
self._mouse = MouseState(self._scale)
|
||||
@@ -388,27 +388,47 @@ class GuiApplication(GuiApplicationExt):
|
||||
|
||||
self._nav_stack.append(widget)
|
||||
widget.show_event()
|
||||
widget.set_enabled(True)
|
||||
|
||||
def pop_widget(self):
|
||||
def pop_widget(self, idx: int | None = None):
|
||||
# Pops widget instantly without animation
|
||||
if len(self._nav_stack) < 2:
|
||||
cloudlog.warning("At least one widget should remain on the stack, ignoring pop!")
|
||||
return
|
||||
|
||||
# re-enable previous widget and pop current
|
||||
# TODO: switch to touch_valid
|
||||
prev_widget = self._nav_stack[-2]
|
||||
prev_widget.set_enabled(True)
|
||||
idx_to_pop = len(self._nav_stack) - 1 if idx is None else idx
|
||||
if idx_to_pop <= 0 or idx_to_pop >= len(self._nav_stack):
|
||||
cloudlog.warning(f"Invalid index {idx_to_pop} to pop, ignoring!")
|
||||
return
|
||||
|
||||
widget = self._nav_stack.pop()
|
||||
# only re-enable previous widget if popping top widget
|
||||
if idx_to_pop == len(self._nav_stack) - 1:
|
||||
prev_widget = self._nav_stack[idx_to_pop - 1]
|
||||
prev_widget.set_enabled(True)
|
||||
|
||||
widget = self._nav_stack.pop(idx_to_pop)
|
||||
widget.hide_event()
|
||||
|
||||
def pop_widgets_to(self, widget):
|
||||
def pop_widgets_to(self, widget: object, callback: Callable[[], None] | None = None, instant: bool = False):
|
||||
# Pops middle widgets instantly without animation then dismisses top, animated out if NavWidget
|
||||
if widget not in self._nav_stack:
|
||||
cloudlog.warning("Widget not in stack, cannot pop to it!")
|
||||
return
|
||||
|
||||
# pops all widgets after specified widget
|
||||
while len(self._nav_stack) > 0 and self._nav_stack[-1] != widget:
|
||||
# Nothing to pop, ensure we still run callback
|
||||
top_widget = self._nav_stack[-1]
|
||||
if top_widget == widget:
|
||||
if callback:
|
||||
callback()
|
||||
return
|
||||
|
||||
# instantly pop widgets in between, then dismiss top widget for animation
|
||||
while len(self._nav_stack) > 1 and self._nav_stack[-2] != widget:
|
||||
self.pop_widget(len(self._nav_stack) - 2)
|
||||
|
||||
if not instant:
|
||||
top_widget.dismiss(callback)
|
||||
else:
|
||||
self.pop_widget()
|
||||
|
||||
def get_active_widget(self):
|
||||
@@ -416,8 +436,13 @@ class GuiApplication(GuiApplicationExt):
|
||||
return self._nav_stack[-1]
|
||||
return None
|
||||
|
||||
def set_nav_stack_tick(self, tick_function: Callable | None):
|
||||
self._nav_stack_tick = tick_function
|
||||
def add_nav_stack_tick(self, tick_function: Callable[[], None]):
|
||||
if tick_function not in self._nav_stack_ticks:
|
||||
self._nav_stack_ticks.append(tick_function)
|
||||
|
||||
def remove_nav_stack_tick(self, tick_function: Callable[[], None]):
|
||||
if tick_function in self._nav_stack_ticks:
|
||||
self._nav_stack_ticks.remove(tick_function)
|
||||
|
||||
def set_should_render(self, should_render: bool):
|
||||
self._should_render = should_render
|
||||
@@ -566,8 +591,8 @@ class GuiApplication(GuiApplicationExt):
|
||||
rl.clear_background(rl.BLACK)
|
||||
|
||||
# Allow a Widget to still run a function regardless of the stack depth
|
||||
if self._nav_stack_tick is not None:
|
||||
self._nav_stack_tick()
|
||||
for tick in self._nav_stack_ticks:
|
||||
tick()
|
||||
|
||||
# Only render top widgets
|
||||
for widget in self._nav_stack[-self._nav_stack_widgets_to_render:]:
|
||||
|
||||
@@ -182,7 +182,7 @@ class Multilang:
|
||||
self.setup()
|
||||
|
||||
def tr(self, text: str) -> str:
|
||||
return self._translations.get(text, text)
|
||||
return self._translations.get(text, text) or text
|
||||
|
||||
def trn(self, singular: str, plural: str, n: int) -> str:
|
||||
if singular in self._plurals:
|
||||
|
||||
@@ -7,13 +7,13 @@ import time
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
from urllib.parse import urlparse
|
||||
from enum import IntEnum
|
||||
import shutil
|
||||
from collections.abc import Callable
|
||||
|
||||
import pyray as rl
|
||||
|
||||
from cereal import log
|
||||
from openpilot.common.filter_simple import FirstOrderFilter
|
||||
from openpilot.common.realtime import config_realtime_process, set_core_affinity
|
||||
from openpilot.common.swaglog import cloudlog
|
||||
from openpilot.common.utils import run_cmd
|
||||
@@ -22,9 +22,9 @@ from openpilot.system.ui.lib.application import gui_app, FontWeight
|
||||
from openpilot.system.ui.lib.wifi_manager import WifiManager
|
||||
from openpilot.system.ui.lib.scroll_panel2 import GuiScrollPanel2
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.nav_widget import NavWidget
|
||||
from openpilot.system.ui.widgets.button import (IconButton, SmallButton, WideRoundedButton, SmallerRoundedButton,
|
||||
SmallCircleIconButton, WidishRoundedButton, SmallRedPillButton,
|
||||
FullRoundedButton)
|
||||
SmallCircleIconButton, WidishRoundedButton, FullRoundedButton)
|
||||
from openpilot.system.ui.widgets.label import UnifiedLabel
|
||||
from openpilot.system.ui.widgets.slider import LargerSlider, SmallSlider
|
||||
from openpilot.selfdrive.ui.mici.layouts.settings.network import WifiUIMici
|
||||
@@ -92,16 +92,6 @@ class NetworkConnectivityMonitor:
|
||||
break
|
||||
|
||||
|
||||
class SetupState(IntEnum):
|
||||
GETTING_STARTED = 0
|
||||
NETWORK_SETUP = 1
|
||||
NETWORK_SETUP_CUSTOM_SOFTWARE = 2
|
||||
SOFTWARE_SELECTION = 3
|
||||
DOWNLOADING = 4
|
||||
DOWNLOAD_FAILED = 5
|
||||
CUSTOM_SOFTWARE_WARNING = 6
|
||||
|
||||
|
||||
class StartPage(Widget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
@@ -110,27 +100,41 @@ class StartPage(Widget):
|
||||
font_weight=FontWeight.DISPLAY, alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER,
|
||||
alignment_vertical=rl.GuiTextAlignmentVertical.TEXT_ALIGN_MIDDLE)
|
||||
|
||||
self._start_bg_txt = gui_app.texture("icons_mici/setup/green_button.png", 520, 224)
|
||||
self._start_bg_pressed_txt = gui_app.texture("icons_mici/setup/green_button_pressed.png", 520, 224)
|
||||
self._start_bg_txt = gui_app.texture("icons_mici/setup/start_button.png", 500, 224, keep_aspect_ratio=False)
|
||||
self._start_bg_pressed_txt = gui_app.texture("icons_mici/setup/start_button_pressed.png", 500, 224, keep_aspect_ratio=False)
|
||||
self._scale_filter = FirstOrderFilter(1.0, 0.1, 1 / gui_app.target_fps)
|
||||
self._click_delay = 0.075
|
||||
|
||||
def _render(self, rect: rl.Rectangle):
|
||||
draw_x = rect.x + (rect.width - self._start_bg_txt.width) / 2
|
||||
draw_y = rect.y + (rect.height - self._start_bg_txt.height) / 2
|
||||
scale = self._scale_filter.update(1.07 if self.is_pressed else 1.0)
|
||||
base_draw_x = rect.x + (rect.width - self._start_bg_txt.width) / 2
|
||||
base_draw_y = rect.y + (rect.height - self._start_bg_txt.height) / 2
|
||||
draw_x = base_draw_x + (self._start_bg_txt.width * (1 - scale)) / 2
|
||||
draw_y = base_draw_y + (self._start_bg_txt.height * (1 - scale)) / 2
|
||||
texture = self._start_bg_pressed_txt if self.is_pressed else self._start_bg_txt
|
||||
rl.draw_texture(texture, int(draw_x), int(draw_y), rl.WHITE)
|
||||
rl.draw_texture_ex(texture, (draw_x, draw_y), 0, scale, rl.WHITE)
|
||||
|
||||
self._title.render(rect)
|
||||
self._title.render(rl.Rectangle(rect.x, rect.y + (draw_y - base_draw_y), rect.width, rect.height))
|
||||
|
||||
|
||||
class SoftwareSelectionPage(Widget):
|
||||
class SoftwareSelectionPage(NavWidget):
|
||||
def __init__(self, use_openpilot_callback: Callable,
|
||||
use_custom_software_callback: Callable):
|
||||
super().__init__()
|
||||
|
||||
self._openpilot_slider = LargerSlider("slide to use\nopenpilot", use_openpilot_callback)
|
||||
self._openpilot_slider.set_enabled(lambda: self.enabled)
|
||||
self._openpilot_slider.set_enabled(lambda: self.enabled and not self.is_dismissing)
|
||||
self._custom_software_slider = LargerSlider("slide to use\ncustom software", use_custom_software_callback, green=False)
|
||||
self._custom_software_slider.set_enabled(lambda: self.enabled)
|
||||
self._custom_software_slider.set_enabled(lambda: self.enabled and not self.is_dismissing)
|
||||
|
||||
def show_event(self):
|
||||
super().show_event()
|
||||
self._nav_bar._alpha = 0.0
|
||||
|
||||
def _update_state(self):
|
||||
super()._update_state()
|
||||
if self.is_dismissing:
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
self._openpilot_slider.reset()
|
||||
@@ -250,6 +254,7 @@ class TermsPage(Widget):
|
||||
pass
|
||||
|
||||
def _render(self, _):
|
||||
rl.draw_rectangle_rec(self._rect, rl.BLACK)
|
||||
scroll_offset = round(self._scroll_panel.update(self._rect, self._content_height + self._continue_button.rect.height + 16))
|
||||
|
||||
if scroll_offset <= self._scrolled_down_offset:
|
||||
@@ -355,52 +360,61 @@ class DownloadingPage(Widget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self._title_label = UnifiedLabel("downloading", 64, text_color=rl.Color(255, 255, 255, int(255 * 0.9)),
|
||||
self._title_label = UnifiedLabel("downloading...", 64, text_color=rl.Color(255, 255, 255, int(255 * 0.9)),
|
||||
font_weight=FontWeight.DISPLAY)
|
||||
self._progress_label = UnifiedLabel("", 128, text_color=rl.Color(255, 255, 255, int(255 * 0.9 * 0.35)),
|
||||
self._progress_label = UnifiedLabel("", 132, text_color=rl.Color(255, 255, 255, int(255 * 0.9 * 0.65)),
|
||||
font_weight=FontWeight.ROMAN, alignment_vertical=rl.GuiTextAlignmentVertical.TEXT_ALIGN_BOTTOM)
|
||||
self._progress = 0
|
||||
|
||||
def show_event(self):
|
||||
super().show_event()
|
||||
self.set_progress(0)
|
||||
|
||||
def set_progress(self, progress: int):
|
||||
self._progress = progress
|
||||
self._progress_label.set_text(f"{progress}%")
|
||||
|
||||
def _render(self, rect: rl.Rectangle):
|
||||
rl.draw_rectangle_rec(rect, rl.BLACK)
|
||||
self._title_label.render(rl.Rectangle(
|
||||
rect.x + 20,
|
||||
rect.y + 10,
|
||||
rect.x + 12,
|
||||
rect.y + 2,
|
||||
rect.width,
|
||||
64,
|
||||
))
|
||||
|
||||
self._progress_label.render(rl.Rectangle(
|
||||
rect.x + 20,
|
||||
rect.y + 20,
|
||||
rect.x + 12,
|
||||
rect.y + 18,
|
||||
rect.width,
|
||||
rect.height,
|
||||
))
|
||||
|
||||
|
||||
class FailedPage(Widget):
|
||||
class FailedPage(NavWidget):
|
||||
def __init__(self, reboot_callback: Callable, retry_callback: Callable, title: str = "download failed"):
|
||||
super().__init__()
|
||||
self.set_back_callback(retry_callback)
|
||||
|
||||
self._title_label = UnifiedLabel(title, 64, text_color=rl.Color(255, 255, 255, int(255 * 0.9)),
|
||||
font_weight=FontWeight.DISPLAY)
|
||||
self._reason_label = UnifiedLabel("", 36, text_color=rl.Color(255, 255, 255, int(255 * 0.9 * 0.65)),
|
||||
font_weight=FontWeight.ROMAN)
|
||||
|
||||
self._reboot_button = SmallRedPillButton("reboot")
|
||||
self._reboot_button.set_click_callback(reboot_callback)
|
||||
self._reboot_button.set_enabled(lambda: self.enabled) # for nav stack
|
||||
self._reboot_slider = SmallSlider("reboot", reboot_callback)
|
||||
self._reboot_slider.set_enabled(lambda: self.enabled) # for nav stack
|
||||
|
||||
self._retry_button = WideRoundedButton("retry")
|
||||
self._retry_button = SmallButton("retry")
|
||||
self._retry_button.set_click_callback(retry_callback)
|
||||
self._retry_button.set_enabled(lambda: self.enabled) # for nav stack
|
||||
|
||||
def set_reason(self, reason: str):
|
||||
self._reason_label.set_text(reason)
|
||||
|
||||
def show_event(self):
|
||||
super().show_event()
|
||||
self._reboot_slider.reset()
|
||||
|
||||
def _render(self, rect: rl.Rectangle):
|
||||
self._title_label.render(rl.Rectangle(
|
||||
rect.x + 8,
|
||||
@@ -416,25 +430,34 @@ class FailedPage(Widget):
|
||||
36,
|
||||
))
|
||||
|
||||
self._reboot_button.render(rl.Rectangle(
|
||||
rect.x + 8,
|
||||
rect.y + rect.height - self._reboot_button.rect.height,
|
||||
self._reboot_button.rect.width,
|
||||
self._reboot_button.rect.height,
|
||||
))
|
||||
|
||||
self._retry_button.set_opacity(1 - self._reboot_slider.slider_percentage)
|
||||
self._retry_button.render(rl.Rectangle(
|
||||
rect.x + 8 + self._reboot_button.rect.width + 8,
|
||||
rect.y + rect.height - self._retry_button.rect.height,
|
||||
self._rect.x + 8,
|
||||
self._rect.y + self._rect.height - self._retry_button.rect.height,
|
||||
self._retry_button.rect.width,
|
||||
self._retry_button.rect.height,
|
||||
))
|
||||
|
||||
self._reboot_slider.render(rl.Rectangle(
|
||||
self._rect.x + self._rect.width - self._reboot_slider.rect.width,
|
||||
self._rect.y + self._rect.height - self._reboot_slider.rect.height,
|
||||
self._reboot_slider.rect.width,
|
||||
self._reboot_slider.rect.height,
|
||||
))
|
||||
|
||||
class NetworkSetupPage(Widget):
|
||||
def __init__(self, wifi_manager, continue_callback: Callable, back_callback: Callable):
|
||||
|
||||
class NetworkSetupPage(NavWidget):
|
||||
def __init__(self, network_monitor: NetworkConnectivityMonitor, continue_callback: Callable[[bool], None],
|
||||
back_callback: Callable[[], None] | None):
|
||||
super().__init__()
|
||||
self._wifi_ui = WifiUIMici(wifi_manager)
|
||||
self.set_back_callback(back_callback)
|
||||
|
||||
self._wifi_manager = WifiManager()
|
||||
self._wifi_manager.set_active(True)
|
||||
self._network_monitor = network_monitor
|
||||
self._custom_software = False
|
||||
self._prev_has_internet = False
|
||||
self._wifi_ui = WifiUIMici(self._wifi_manager)
|
||||
|
||||
self._no_wifi_txt = gui_app.texture("icons_mici/settings/network/wifi_strength_slash.png", 58, 50)
|
||||
self._wifi_full_txt = gui_app.texture("icons_mici/settings/network/wifi_strength_full.png", 58, 50)
|
||||
@@ -452,18 +475,39 @@ class NetworkSetupPage(Widget):
|
||||
|
||||
self._continue_button = WidishRoundedButton("continue")
|
||||
self._continue_button.set_enabled(False)
|
||||
self._continue_button.set_click_callback(continue_callback)
|
||||
self._continue_button.set_click_callback(lambda: continue_callback(self._custom_software))
|
||||
|
||||
def set_has_internet(self, has_internet: bool):
|
||||
gui_app.add_nav_stack_tick(self._nav_stack_tick)
|
||||
|
||||
def show_event(self):
|
||||
super().show_event()
|
||||
self._prev_has_internet = False
|
||||
self._network_monitor.reset()
|
||||
self._set_has_internet(False)
|
||||
|
||||
def _nav_stack_tick(self):
|
||||
self._wifi_manager.process_callbacks()
|
||||
|
||||
has_internet = self._network_monitor.network_connected.is_set()
|
||||
if has_internet != self._prev_has_internet:
|
||||
self._set_has_internet(has_internet)
|
||||
if has_internet:
|
||||
gui_app.pop_widgets_to(self)
|
||||
self._prev_has_internet = has_internet
|
||||
|
||||
def _set_has_internet(self, has_internet: bool):
|
||||
if has_internet:
|
||||
self._network_header.set_title("connected to internet")
|
||||
self._network_header.set_icon(self._wifi_full_txt)
|
||||
self._continue_button.set_enabled(self.enabled)
|
||||
self._continue_button.set_enabled(lambda: self.enabled)
|
||||
else:
|
||||
self._network_header.set_title(self._waiting_text)
|
||||
self._network_header.set_icon(self._no_wifi_txt)
|
||||
self._continue_button.set_enabled(False)
|
||||
|
||||
def set_custom_software(self, custom_software: bool):
|
||||
self._custom_software = custom_software
|
||||
|
||||
def _render(self, _):
|
||||
self._network_header.render(rl.Rectangle(
|
||||
self._rect.x + 16,
|
||||
@@ -497,122 +541,55 @@ class NetworkSetupPage(Widget):
|
||||
class Setup(Widget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.state = SetupState.GETTING_STARTED
|
||||
self.failed_url = ""
|
||||
self.failed_reason = ""
|
||||
self.download_url = ""
|
||||
self.download_progress = 0
|
||||
self.download_thread = None
|
||||
self._wifi_manager = WifiManager()
|
||||
self._wifi_manager.set_active(True)
|
||||
self._download_failed_reason: str | None = None
|
||||
|
||||
self._network_monitor = NetworkConnectivityMonitor()
|
||||
self._network_monitor.start()
|
||||
self._prev_has_internet = False
|
||||
gui_app.set_nav_stack_tick(self._nav_stack_tick)
|
||||
|
||||
def getting_started_button_callback():
|
||||
self._software_selection_page.reset()
|
||||
gui_app.push_widget(self._software_selection_page)
|
||||
|
||||
self._start_page = StartPage()
|
||||
self._start_page.set_click_callback(self._getting_started_button_callback)
|
||||
self._start_page.set_click_callback(getting_started_button_callback)
|
||||
self._start_page.set_enabled(lambda: self.enabled) # for nav stack
|
||||
|
||||
self._network_setup_page = NetworkSetupPage(self._wifi_manager, self._network_setup_continue_button_callback,
|
||||
self._network_setup_back_button_callback)
|
||||
# TODO: change these to touch_valid
|
||||
self._network_setup_page.set_enabled(lambda: self.enabled) # for nav stack
|
||||
self._network_setup_page = NetworkSetupPage(self._network_monitor, self._network_setup_continue_button_callback,
|
||||
self._pop_to_software_selection)
|
||||
self._software_selection_page = SoftwareSelectionPage(self._use_openpilot, lambda: gui_app.push_widget(self._custom_software_warning_page))
|
||||
|
||||
self._software_selection_page = SoftwareSelectionPage(self._software_selection_continue_button_callback,
|
||||
self._software_selection_custom_software_button_callback)
|
||||
self._software_selection_page.set_enabled(lambda: self.enabled) # for nav stack
|
||||
self._download_failed_page = FailedPage(HARDWARE.reboot, self._pop_to_software_selection)
|
||||
|
||||
self._download_failed_page = FailedPage(HARDWARE.reboot, self._download_failed_startover_button_callback)
|
||||
self._download_failed_page.set_enabled(lambda: self.enabled) # for nav stack
|
||||
|
||||
self._custom_software_warning_page = CustomSoftwareWarningPage(self._software_selection_custom_software_continue,
|
||||
self._custom_software_warning_back_button_callback)
|
||||
self._custom_software_warning_page.set_enabled(lambda: self.enabled) # for nav stack
|
||||
self._custom_software_warning_page = CustomSoftwareWarningPage(self._software_selection_custom_software_continue, self._pop_to_software_selection)
|
||||
|
||||
self._downloading_page = DownloadingPage()
|
||||
|
||||
gui_app.add_nav_stack_tick(self._nav_stack_tick)
|
||||
|
||||
def _nav_stack_tick(self):
|
||||
has_internet = self._network_monitor.network_connected.is_set()
|
||||
if has_internet and not self._prev_has_internet:
|
||||
gui_app.pop_widgets_to(self)
|
||||
self._prev_has_internet = has_internet
|
||||
self._downloading_page.set_progress(self.download_progress)
|
||||
|
||||
def _update_state(self):
|
||||
self._wifi_manager.process_callbacks()
|
||||
|
||||
def _set_state(self, state: SetupState):
|
||||
self.state = state
|
||||
if self.state == SetupState.SOFTWARE_SELECTION:
|
||||
self._software_selection_page.reset()
|
||||
elif self.state == SetupState.CUSTOM_SOFTWARE_WARNING:
|
||||
self._custom_software_warning_page.reset()
|
||||
|
||||
if self.state in (SetupState.NETWORK_SETUP, SetupState.NETWORK_SETUP_CUSTOM_SOFTWARE):
|
||||
self._network_setup_page.show_event()
|
||||
self._network_monitor.reset()
|
||||
else:
|
||||
self._network_setup_page.hide_event()
|
||||
if self._download_failed_reason is not None:
|
||||
reason = self._download_failed_reason
|
||||
self._download_failed_reason = None
|
||||
self._download_failed_page.set_reason(reason)
|
||||
gui_app.pop_widgets_to(self._software_selection_page, instant=True) # don't reset sliders
|
||||
gui_app.push_widget(self._download_failed_page)
|
||||
|
||||
def _render(self, rect: rl.Rectangle):
|
||||
if self.state == SetupState.GETTING_STARTED:
|
||||
self._start_page.render(rect)
|
||||
elif self.state in (SetupState.NETWORK_SETUP, SetupState.NETWORK_SETUP_CUSTOM_SOFTWARE):
|
||||
self.render_network_setup(rect)
|
||||
elif self.state == SetupState.SOFTWARE_SELECTION:
|
||||
self._software_selection_page.render(rect)
|
||||
elif self.state == SetupState.CUSTOM_SOFTWARE_WARNING:
|
||||
self._custom_software_warning_page.render(rect)
|
||||
elif self.state == SetupState.DOWNLOADING:
|
||||
self.render_downloading(rect)
|
||||
elif self.state == SetupState.DOWNLOAD_FAILED:
|
||||
self._download_failed_page.render(rect)
|
||||
|
||||
def _custom_software_warning_back_button_callback(self):
|
||||
self._set_state(SetupState.SOFTWARE_SELECTION)
|
||||
|
||||
def _getting_started_button_callback(self):
|
||||
self._set_state(SetupState.SOFTWARE_SELECTION)
|
||||
|
||||
def _software_selection_continue_button_callback(self):
|
||||
self.use_openpilot()
|
||||
|
||||
def _software_selection_custom_software_button_callback(self):
|
||||
self._set_state(SetupState.CUSTOM_SOFTWARE_WARNING)
|
||||
|
||||
def _software_selection_custom_software_continue(self):
|
||||
self._set_state(SetupState.NETWORK_SETUP_CUSTOM_SOFTWARE)
|
||||
|
||||
def _download_failed_startover_button_callback(self):
|
||||
self._set_state(SetupState.GETTING_STARTED)
|
||||
|
||||
def _network_setup_back_button_callback(self):
|
||||
self._set_state(SetupState.SOFTWARE_SELECTION)
|
||||
|
||||
def _network_setup_continue_button_callback(self):
|
||||
if self.state == SetupState.NETWORK_SETUP:
|
||||
self.download(OPENPILOT_URL)
|
||||
elif self.state == SetupState.NETWORK_SETUP_CUSTOM_SOFTWARE:
|
||||
def handle_keyboard_result(text):
|
||||
url = text.strip()
|
||||
if url:
|
||||
self.download(url)
|
||||
|
||||
keyboard = BigInputDialog("custom software URL", confirm_callback=handle_keyboard_result)
|
||||
gui_app.push_widget(keyboard)
|
||||
self._start_page.render(rect)
|
||||
|
||||
def close(self):
|
||||
self._network_monitor.stop()
|
||||
|
||||
def render_network_setup(self, rect: rl.Rectangle):
|
||||
has_internet = self._network_monitor.network_connected.is_set()
|
||||
self._network_setup_page.set_has_internet(has_internet)
|
||||
self._network_setup_page.render(rect)
|
||||
def _pop_to_software_selection(self):
|
||||
# reset sliders after dismiss completes
|
||||
gui_app.pop_widgets_to(self._software_selection_page, self._software_selection_page.reset)
|
||||
|
||||
def render_downloading(self, rect: rl.Rectangle):
|
||||
self._downloading_page.set_progress(self.download_progress)
|
||||
self._downloading_page.render(rect)
|
||||
|
||||
def use_openpilot(self):
|
||||
def _use_openpilot(self):
|
||||
if os.path.isdir(INSTALL_PATH) and os.path.isfile(VALID_CACHE_PATH):
|
||||
os.remove(VALID_CACHE_PATH)
|
||||
with open(TMP_CONTINUE_PATH, "w") as f:
|
||||
@@ -625,17 +602,40 @@ class Setup(Widget):
|
||||
time.sleep(0.1)
|
||||
gui_app.request_close()
|
||||
else:
|
||||
self._set_state(SetupState.NETWORK_SETUP)
|
||||
self._push_network_setup(custom_software=False)
|
||||
|
||||
def download(self, url: str):
|
||||
def _push_network_setup(self, custom_software: bool):
|
||||
self._network_setup_page.set_custom_software(custom_software)
|
||||
gui_app.push_widget(self._network_setup_page)
|
||||
|
||||
def _software_selection_custom_software_continue(self):
|
||||
gui_app.pop_widgets_to(self._software_selection_page, instant=True) # don't reset sliders
|
||||
self._push_network_setup(custom_software=True)
|
||||
|
||||
def _network_setup_continue_button_callback(self, custom_software):
|
||||
if not custom_software:
|
||||
gui_app.pop_widgets_to(self._software_selection_page, instant=True) # don't reset sliders
|
||||
self._download(OPENPILOT_URL)
|
||||
else:
|
||||
def handle_keyboard_result(text):
|
||||
url = text.strip()
|
||||
if url:
|
||||
gui_app.pop_widgets_to(self._software_selection_page, instant=True) # don't reset sliders
|
||||
self._download(url)
|
||||
|
||||
keyboard = BigInputDialog("custom software URL", confirm_callback=handle_keyboard_result)
|
||||
gui_app.push_widget(keyboard)
|
||||
|
||||
def _download(self, url: str):
|
||||
# autocomplete incomplete URLs
|
||||
if re.match("^([^/.]+)/([^/]+)$", url):
|
||||
url = f"https://installer.comma.ai/{url}"
|
||||
|
||||
parsed = urlparse(url, scheme='https')
|
||||
self.download_url = (urlparse(f"https://{url}") if not parsed.netloc else parsed).geturl()
|
||||
self.download_progress = 0
|
||||
|
||||
self._set_state(SetupState.DOWNLOADING)
|
||||
gui_app.push_widget(self._downloading_page)
|
||||
|
||||
self.download_thread = threading.Thread(target=self._download_thread, daemon=True)
|
||||
self.download_thread.start()
|
||||
@@ -666,7 +666,6 @@ class Setup(Widget):
|
||||
|
||||
if total_size:
|
||||
self.download_progress = int(downloaded * 100 / total_size)
|
||||
self._downloading_page.set_progress(self.download_progress)
|
||||
|
||||
is_elf = False
|
||||
with open(tmpfile, 'rb') as f:
|
||||
@@ -674,7 +673,7 @@ class Setup(Widget):
|
||||
is_elf = header == b'\x7fELF'
|
||||
|
||||
if not is_elf:
|
||||
self.download_failed(self.download_url, "No custom software found at this URL.")
|
||||
self._download_failed_reason = "No custom software found at this URL."
|
||||
return
|
||||
|
||||
# AGNOS might try to execute the installer before this process exits.
|
||||
@@ -691,17 +690,9 @@ class Setup(Widget):
|
||||
|
||||
except urllib.error.HTTPError as e:
|
||||
if e.code == 409:
|
||||
error_msg = "Incompatible sunnypilot version"
|
||||
self.download_failed(self.download_url, error_msg)
|
||||
self._download_failed_reason = "Incompatible sunnypilot version"
|
||||
except Exception:
|
||||
error_msg = "Invalid URL"
|
||||
self.download_failed(self.download_url, error_msg)
|
||||
|
||||
def download_failed(self, url: str, reason: str):
|
||||
self.failed_url = url
|
||||
self.failed_reason = reason
|
||||
self._download_failed_page.set_reason(reason)
|
||||
self._set_state(SetupState.DOWNLOAD_FAILED)
|
||||
self._download_failed_reason = "Invalid URL"
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -7,10 +7,9 @@ from enum import IntEnum
|
||||
|
||||
from openpilot.system.hardware import HARDWARE
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight
|
||||
from openpilot.system.ui.lib.text_measure import measure_text_cached
|
||||
from openpilot.system.ui.lib.wifi_manager import WifiManager
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.label import gui_text_box, gui_label, UnifiedLabel
|
||||
from openpilot.system.ui.widgets.label import UnifiedLabel
|
||||
from openpilot.system.ui.widgets.button import FullRoundedButton
|
||||
from openpilot.system.ui.mici_setup import NetworkSetupPage, FailedPage, NetworkConnectivityMonitor
|
||||
|
||||
@@ -47,7 +46,7 @@ class Updater(Widget):
|
||||
self._continue_button = FullRoundedButton("continue")
|
||||
self._continue_button.set_click_callback(lambda: self.set_current_screen(Screen.WIFI))
|
||||
|
||||
self._title_label = UnifiedLabel("update required", 48, text_color=rl.Color(255, 115, 0, 255),
|
||||
self._title_label = UnifiedLabel("update required", 48, text_color=rl.Color(255, 255, 255, int(255 * 0.9)),
|
||||
font_weight=FontWeight.DISPLAY)
|
||||
self._subtitle_label = UnifiedLabel("The download size is approximately 1GB.", 36,
|
||||
text_color=rl.Color(255, 255, 255, int(255 * 0.9)),
|
||||
@@ -56,6 +55,12 @@ class Updater(Widget):
|
||||
self._update_failed_page = FailedPage(HARDWARE.reboot, self._update_failed_retry_callback,
|
||||
title="update failed")
|
||||
|
||||
self._progress_title_label = UnifiedLabel("", 64, text_color=rl.Color(255, 255, 255, int(255 * 0.9)),
|
||||
font_weight=FontWeight.DISPLAY, line_height=0.8)
|
||||
self._progress_percent_label = UnifiedLabel("", 132, text_color=rl.Color(255, 255, 255, int(255 * 0.9 * 0.65)),
|
||||
font_weight=FontWeight.ROMAN,
|
||||
alignment_vertical=rl.GuiTextAlignmentVertical.TEXT_ALIGN_BOTTOM)
|
||||
|
||||
def _network_setup_back_callback(self):
|
||||
self.set_current_screen(Screen.PROMPT)
|
||||
|
||||
@@ -139,20 +144,21 @@ class Updater(Widget):
|
||||
))
|
||||
|
||||
def render_progress_screen(self, rect: rl.Rectangle):
|
||||
title_rect = rl.Rectangle(self._rect.x + 6, self._rect.y - 5, self._rect.width - 12, self._rect.height - 8)
|
||||
if ' ' in self.progress_text:
|
||||
font_size = 62
|
||||
else:
|
||||
font_size = 82
|
||||
gui_text_box(title_rect, self.progress_text, font_size, font_weight=FontWeight.DISPLAY,
|
||||
color=rl.Color(255, 255, 255, int(255 * 0.9)))
|
||||
self._progress_title_label.set_text(self.progress_text.replace("_", "_\n") + "...")
|
||||
self._progress_title_label.render(rl.Rectangle(
|
||||
rect.x + 12,
|
||||
rect.y + 2,
|
||||
rect.width,
|
||||
self._progress_title_label.get_content_height(int(rect.width - 20)),
|
||||
))
|
||||
|
||||
progress_value = f"{self.progress_value}%"
|
||||
text_height = measure_text_cached(gui_app.font(FontWeight.ROMAN), progress_value, 128).y
|
||||
progress_rect = rl.Rectangle(self._rect.x + 6, self._rect.y + self._rect.height - text_height + 18,
|
||||
self._rect.width - 12, text_height)
|
||||
gui_label(progress_rect, progress_value, 128, font_weight=FontWeight.ROMAN,
|
||||
color=rl.Color(255, 255, 255, int(255 * 0.9 * 0.35)))
|
||||
self._progress_percent_label.set_text(f"{self.progress_value}%")
|
||||
self._progress_percent_label.render(rl.Rectangle(
|
||||
rect.x + 12,
|
||||
rect.y + 18,
|
||||
rect.width,
|
||||
rect.height,
|
||||
))
|
||||
|
||||
def _update_state(self):
|
||||
self._wifi_manager.process_callbacks()
|
||||
|
||||
@@ -30,6 +30,8 @@ class Widget(abc.ABC):
|
||||
self._enabled: bool | Callable[[], bool] = True
|
||||
self._is_visible: bool | Callable[[], bool] = True
|
||||
self._touch_valid_callback: Callable[[], bool] | None = None
|
||||
self._click_delay: float | None = None # seconds to hold is_pressed after release
|
||||
self._click_release_time: float | None = None
|
||||
self._click_callback: Callable[[], None] | None = None
|
||||
self._multi_touch = False
|
||||
self.__was_awake = True
|
||||
@@ -51,7 +53,8 @@ class Widget(abc.ABC):
|
||||
|
||||
@property
|
||||
def is_pressed(self) -> bool:
|
||||
return any(self.__is_pressed)
|
||||
# if actually pressed or holding after release
|
||||
return any(self.__is_pressed) or self._click_release_time is not None
|
||||
|
||||
@property
|
||||
def enabled(self) -> bool:
|
||||
@@ -98,6 +101,9 @@ class Widget(abc.ABC):
|
||||
|
||||
self._update_state()
|
||||
|
||||
if self._click_release_time is not None and rl.get_time() >= self._click_release_time:
|
||||
self._click_release_time = None
|
||||
|
||||
if not self.is_visible:
|
||||
return None
|
||||
|
||||
@@ -182,6 +188,8 @@ class Widget(abc.ABC):
|
||||
|
||||
def _handle_mouse_release(self, mouse_pos: MousePos) -> None:
|
||||
"""Optionally handle mouse release events."""
|
||||
if self._click_delay is not None:
|
||||
self._click_release_time = rl.get_time() + self._click_delay
|
||||
if self._click_callback:
|
||||
self._click_callback()
|
||||
|
||||
@@ -195,3 +203,9 @@ class Widget(abc.ABC):
|
||||
|
||||
def hide_event(self):
|
||||
"""Optionally handle hide event. Parent must manually call this"""
|
||||
|
||||
def dismiss(self, callback: Callable[[], None] | None = None):
|
||||
"""Immediately dismiss the widget, firing the callback after."""
|
||||
gui_app.pop_widget()
|
||||
if callback:
|
||||
callback()
|
||||
|
||||
@@ -322,7 +322,7 @@ class MiciKeyboard(Widget):
|
||||
self._selected_key_filter.update(self._closest_key[0] is not None)
|
||||
|
||||
# unselect key after animation plays
|
||||
if self._unselect_key_t is not None and rl.get_time() > self._unselect_key_t:
|
||||
if (self._unselect_key_t is not None and rl.get_time() > self._unselect_key_t) or not self.enabled:
|
||||
self._closest_key = (None, float('inf'))
|
||||
self._unselect_key_t = None
|
||||
self._selected_key_t = None
|
||||
|
||||
@@ -15,11 +15,13 @@ NAV_BAR_MARGIN = 6
|
||||
NAV_BAR_WIDTH = 205
|
||||
NAV_BAR_HEIGHT = 8
|
||||
|
||||
DISMISS_PUSH_OFFSET = 50 + NAV_BAR_MARGIN + NAV_BAR_HEIGHT # px extra to push down when dismissing
|
||||
DISMISS_TIME_SECONDS = 2.0
|
||||
DISMISS_PUSH_OFFSET = NAV_BAR_MARGIN + NAV_BAR_HEIGHT + 50 # px extra to push down when dismissing
|
||||
DISMISS_ANIMATION_RC = 0.2 # slightly slower for non-user triggered dismiss animation
|
||||
|
||||
|
||||
class NavBar(Widget):
|
||||
FADE_AFTER_SECONDS = 2.0
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.set_rect(rl.Rectangle(0, 0, NAV_BAR_WIDTH, NAV_BAR_HEIGHT))
|
||||
@@ -38,7 +40,7 @@ class NavBar(Widget):
|
||||
self._fade_time = rl.get_time()
|
||||
|
||||
def _render(self, _):
|
||||
if rl.get_time() - self._fade_time > DISMISS_TIME_SECONDS:
|
||||
if rl.get_time() - self._fade_time > self.FADE_AFTER_SECONDS:
|
||||
self._alpha = 0.0
|
||||
alpha = self._alpha_filter.update(self._alpha)
|
||||
|
||||
@@ -55,124 +57,109 @@ class NavWidget(Widget, abc.ABC):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._back_callback: Callable[[], None] | None = None
|
||||
self._back_button_start_pos: MousePos | None = None
|
||||
self._swiping_away = False # currently swiping away
|
||||
self._can_swipe_away = True # swipe away is blocked after certain horizontal movement
|
||||
# State
|
||||
self._drag_start_pos: MousePos | None = None # cleared after certain amount of horizontal movement
|
||||
self._dragging_down = False # swiped down enough to trigger dismissing on release
|
||||
self._playing_dismiss_animation = False # released and animating away
|
||||
self._y_pos_filter = BounceFilter(0.0, 0.1, 1 / gui_app.target_fps, bounce=1)
|
||||
|
||||
self._pos_filter = BounceFilter(0.0, 0.1, 1 / gui_app.target_fps, bounce=1)
|
||||
self._playing_dismiss_animation = False
|
||||
self._trigger_animate_in = False
|
||||
self._nav_bar_show_time = 0.0
|
||||
self._back_enabled: bool | Callable[[], bool] = True
|
||||
self._back_callback: Callable[[], None] | None = None # persistent callback for any back navigation
|
||||
self._dismiss_callback: Callable[[], None] | None = None # transient callback for programmatic dismiss
|
||||
|
||||
# TODO: move this state into NavBar
|
||||
self._nav_bar = NavBar()
|
||||
|
||||
self._nav_bar_show_time = 0.0
|
||||
self._nav_bar_y_filter = FirstOrderFilter(0.0, 0.1, 1 / gui_app.target_fps)
|
||||
|
||||
@property
|
||||
def back_enabled(self) -> bool:
|
||||
return self._back_enabled() if callable(self._back_enabled) else self._back_enabled
|
||||
|
||||
def set_back_enabled(self, enabled: bool | Callable[[], bool]) -> None:
|
||||
self._back_enabled = enabled
|
||||
def _back_enabled(self) -> bool:
|
||||
# Children can override this to block swipe away, like when not at
|
||||
# the top of a vertical scroll panel to prevent erroneous swipes
|
||||
return True
|
||||
|
||||
def set_back_callback(self, callback: Callable[[], None]) -> None:
|
||||
self._back_callback = callback
|
||||
|
||||
def _handle_mouse_event(self, mouse_event: MouseEvent) -> None:
|
||||
# FIXME: disabling this widget on new push_widget still causes this widget to track mouse events without mouse down
|
||||
super()._handle_mouse_event(mouse_event)
|
||||
|
||||
if not self.back_enabled:
|
||||
self._back_button_start_pos = None
|
||||
self._swiping_away = False
|
||||
self._can_swipe_away = True
|
||||
# Don't let touch events change filter state during dismiss animation
|
||||
if self._playing_dismiss_animation:
|
||||
return
|
||||
|
||||
if mouse_event.left_pressed:
|
||||
# user is able to swipe away if starting near top of screen, or anywhere if scroller is at top
|
||||
self._pos_filter.update_alpha(0.04)
|
||||
# user is able to swipe away if starting near top of screen
|
||||
self._y_pos_filter.update_alpha(0.04)
|
||||
in_dismiss_area = mouse_event.pos.y < self._rect.height * self.BACK_TOUCH_AREA_PERCENTAGE
|
||||
|
||||
# TODO: remove vertical scrolling and then this hacky logic to check if scroller is at top
|
||||
scroller_at_top = False
|
||||
vertical_scroller = False
|
||||
# TODO: -20? snapping in WiFi dialog can make offset not be positive at the top
|
||||
if hasattr(self, '_scroller'):
|
||||
scroller_at_top = self._scroller.scroll_panel.get_offset() >= -20 and not self._scroller._horizontal
|
||||
vertical_scroller = not self._scroller._horizontal
|
||||
elif hasattr(self, '_scroll_panel'):
|
||||
scroller_at_top = self._scroll_panel.get_offset() >= -20 and not self._scroll_panel._horizontal
|
||||
vertical_scroller = not self._scroll_panel._horizontal
|
||||
|
||||
# Vertical scrollers need to be at the top to swipe away to prevent erroneous swipes
|
||||
if (not vertical_scroller and in_dismiss_area) or scroller_at_top:
|
||||
self._can_swipe_away = True
|
||||
self._back_button_start_pos = mouse_event.pos
|
||||
if in_dismiss_area and self._back_enabled():
|
||||
self._drag_start_pos = mouse_event.pos
|
||||
|
||||
elif mouse_event.left_down:
|
||||
if self._back_button_start_pos is not None:
|
||||
if self._drag_start_pos is not None:
|
||||
# block swiping away if too much horizontal or upward movement
|
||||
horizontal_movement = abs(mouse_event.pos.x - self._back_button_start_pos.x) > BLOCK_SWIPE_AWAY_THRESHOLD
|
||||
upward_movement = mouse_event.pos.y - self._back_button_start_pos.y < -BLOCK_SWIPE_AWAY_THRESHOLD
|
||||
if not self._swiping_away and (horizontal_movement or upward_movement):
|
||||
self._can_swipe_away = False
|
||||
self._back_button_start_pos = None
|
||||
# block (lock-in) threshold is higher than start dismissing
|
||||
horizontal_movement = abs(mouse_event.pos.x - self._drag_start_pos.x) > BLOCK_SWIPE_AWAY_THRESHOLD
|
||||
upward_movement = mouse_event.pos.y - self._drag_start_pos.y < -BLOCK_SWIPE_AWAY_THRESHOLD
|
||||
|
||||
# block horizontal swiping if now swiping away
|
||||
if self._can_swipe_away:
|
||||
if mouse_event.pos.y - self._back_button_start_pos.y > START_DISMISSING_THRESHOLD:
|
||||
self._swiping_away = True
|
||||
if not (horizontal_movement or upward_movement):
|
||||
# no blocking movement, check if we should start dismissing
|
||||
if mouse_event.pos.y - self._drag_start_pos.y > START_DISMISSING_THRESHOLD:
|
||||
self._dragging_down = True
|
||||
else:
|
||||
if not self._dragging_down:
|
||||
self._drag_start_pos = None
|
||||
|
||||
elif mouse_event.left_released:
|
||||
self._pos_filter.update_alpha(0.1)
|
||||
# reset rc for either slide up or down animation
|
||||
self._y_pos_filter.update_alpha(0.1)
|
||||
|
||||
# if far enough, trigger back navigation callback
|
||||
if self._back_button_start_pos is not None:
|
||||
if mouse_event.pos.y - self._back_button_start_pos.y > SWIPE_AWAY_THRESHOLD:
|
||||
if self._drag_start_pos is not None:
|
||||
if mouse_event.pos.y - self._drag_start_pos.y > SWIPE_AWAY_THRESHOLD:
|
||||
self._playing_dismiss_animation = True
|
||||
|
||||
self._back_button_start_pos = None
|
||||
self._swiping_away = False
|
||||
self._drag_start_pos = None
|
||||
self._dragging_down = False
|
||||
|
||||
def _update_state(self):
|
||||
super()._update_state()
|
||||
|
||||
if self._trigger_animate_in:
|
||||
self._pos_filter.x = self._rect.height
|
||||
self._nav_bar_y_filter.x = -NAV_BAR_MARGIN - NAV_BAR_HEIGHT
|
||||
self._nav_bar_show_time = rl.get_time()
|
||||
self._trigger_animate_in = False
|
||||
|
||||
new_y = 0.0
|
||||
|
||||
if not self.enabled:
|
||||
self._back_button_start_pos = None
|
||||
if self._dragging_down:
|
||||
self._nav_bar.set_alpha(1.0)
|
||||
|
||||
# TODO: why is this not in handle_mouse_event? have to hack above
|
||||
if self._back_button_start_pos is not None:
|
||||
# FIXME: disabling this widget on new push_widget still causes this widget to track mouse events without mouse down
|
||||
if not self.enabled:
|
||||
self._drag_start_pos = None
|
||||
|
||||
if self._drag_start_pos is not None:
|
||||
last_mouse_event = gui_app.last_mouse_event
|
||||
# push entire widget as user drags it away
|
||||
new_y = max(last_mouse_event.pos.y - self._back_button_start_pos.y, 0)
|
||||
new_y = max(last_mouse_event.pos.y - self._drag_start_pos.y, 0)
|
||||
if new_y < SWIPE_AWAY_THRESHOLD:
|
||||
new_y /= 2 # resistance until mouse release would dismiss widget
|
||||
|
||||
if self._swiping_away:
|
||||
self._nav_bar.set_alpha(1.0)
|
||||
|
||||
if self._playing_dismiss_animation:
|
||||
new_y = self._rect.height + DISMISS_PUSH_OFFSET
|
||||
|
||||
new_y = round(self._pos_filter.update(new_y))
|
||||
if abs(new_y) < 1 and self._pos_filter.velocity.x == 0.0:
|
||||
new_y = self._pos_filter.x = 0.0
|
||||
new_y = round(self._y_pos_filter.update(new_y))
|
||||
if abs(new_y) < 1 and self._y_pos_filter.velocity.x == 0.0:
|
||||
new_y = self._y_pos_filter.x = 0.0
|
||||
|
||||
if new_y > self._rect.height + DISMISS_PUSH_OFFSET - 10:
|
||||
gui_app.pop_widget()
|
||||
|
||||
if self._back_callback is not None:
|
||||
self._back_callback()
|
||||
|
||||
if self._dismiss_callback is not None:
|
||||
self._dismiss_callback()
|
||||
self._dismiss_callback = None
|
||||
|
||||
self._playing_dismiss_animation = False
|
||||
self._back_button_start_pos = None
|
||||
self._swiping_away = False
|
||||
self._drag_start_pos = None
|
||||
self._dragging_down = False
|
||||
|
||||
self.set_position(self._rect.x, new_y)
|
||||
|
||||
@@ -187,32 +174,46 @@ class NavWidget(Widget, abc.ABC):
|
||||
def render(self, rect: rl.Rectangle | None = None) -> bool | int | None:
|
||||
ret = super().render(rect)
|
||||
|
||||
if self.back_enabled:
|
||||
bar_x = self._rect.x + (self._rect.width - self._nav_bar.rect.width) / 2
|
||||
nav_bar_delayed = rl.get_time() - self._nav_bar_show_time < 0.4
|
||||
# User dragging or dismissing, nav bar follows NavWidget
|
||||
if self._back_button_start_pos is not None or self._playing_dismiss_animation:
|
||||
self._nav_bar_y_filter.x = NAV_BAR_MARGIN + self._pos_filter.x
|
||||
# Waiting to show
|
||||
elif nav_bar_delayed:
|
||||
self._nav_bar_y_filter.x = -NAV_BAR_MARGIN - NAV_BAR_HEIGHT
|
||||
# Animate back to top
|
||||
else:
|
||||
self._nav_bar_y_filter.update(NAV_BAR_MARGIN)
|
||||
bar_x = self._rect.x + (self._rect.width - self._nav_bar.rect.width) / 2
|
||||
nav_bar_delayed = rl.get_time() - self._nav_bar_show_time < 0.4
|
||||
# User dragging or dismissing, nav bar follows NavWidget
|
||||
if self._drag_start_pos is not None or self._playing_dismiss_animation:
|
||||
self._nav_bar_y_filter.x = NAV_BAR_MARGIN + self._y_pos_filter.x
|
||||
# Waiting to show
|
||||
elif nav_bar_delayed:
|
||||
self._nav_bar_y_filter.x = -NAV_BAR_MARGIN - NAV_BAR_HEIGHT
|
||||
# Animate back to top
|
||||
else:
|
||||
self._nav_bar_y_filter.update(NAV_BAR_MARGIN)
|
||||
|
||||
self._nav_bar.set_position(bar_x, round(self._nav_bar_y_filter.x))
|
||||
self._nav_bar.render()
|
||||
self._nav_bar.set_position(bar_x, round(self._nav_bar_y_filter.x))
|
||||
self._nav_bar.render()
|
||||
|
||||
return ret
|
||||
|
||||
@property
|
||||
def is_dismissing(self) -> bool:
|
||||
return self._dragging_down or self._playing_dismiss_animation
|
||||
|
||||
def dismiss(self, callback: Callable[[], None] | None = None):
|
||||
"""Programmatically trigger the dismiss animation. Calls pop_widget when done, then callback."""
|
||||
if not self._playing_dismiss_animation:
|
||||
self._playing_dismiss_animation = True
|
||||
self._y_pos_filter.update_alpha(DISMISS_ANIMATION_RC)
|
||||
self._dismiss_callback = callback
|
||||
|
||||
def show_event(self):
|
||||
super().show_event()
|
||||
# FIXME: we don't know the height of the rect at first show_event since it's before the first render :(
|
||||
# so we need this hacky bool for now
|
||||
self._trigger_animate_in = True
|
||||
self._nav_bar.show_event()
|
||||
|
||||
# Reset state
|
||||
self._pos_filter.update_alpha(0.1)
|
||||
self._back_button_start_pos = None
|
||||
self._swiping_away = False
|
||||
self._drag_start_pos = None
|
||||
self._dragging_down = False
|
||||
self._playing_dismiss_animation = False
|
||||
self._dismiss_callback = None
|
||||
# Start NavWidget off-screen, no matter how tall it is
|
||||
self._y_pos_filter.update_alpha(0.1)
|
||||
self._y_pos_filter.x = gui_app.height
|
||||
|
||||
self._nav_bar_y_filter.x = -NAV_BAR_MARGIN - NAV_BAR_HEIGHT
|
||||
self._nav_bar_show_time = rl.get_time()
|
||||
|
||||
@@ -443,4 +443,27 @@ class NavScroller(NavWidget, Scroller):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
# pass down enabled to child widget for nav stack + disable while swiping away NavWidget
|
||||
self._scroller.set_enabled(lambda: self.enabled and not self._swiping_away)
|
||||
self._scroller.set_enabled(lambda: self.enabled and not self.is_dismissing)
|
||||
|
||||
def _back_enabled(self) -> bool:
|
||||
# Vertical scrollers need to be at the top to swipe away to prevent erroneous swipes
|
||||
# TODO: only used for offroad alerts, remove when horizontal
|
||||
return self._scroller._horizontal or self._scroller.scroll_panel.get_offset() >= -20 # some tolerance
|
||||
|
||||
|
||||
# TODO: only used for a few vertical scrollers, remove when horizontal
|
||||
class NavRawScrollPanel(NavWidget):
|
||||
# can swipe anywhere, only when at top
|
||||
BACK_TOUCH_AREA_PERCENTAGE = 1.0
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._scroll_panel = GuiScrollPanel2(horizontal=False)
|
||||
self._scroll_panel.set_enabled(lambda: self.enabled and not self.is_dismissing)
|
||||
|
||||
def show_event(self):
|
||||
super().show_event()
|
||||
self._scroll_panel.set_offset(0)
|
||||
|
||||
def _back_enabled(self) -> bool:
|
||||
return self._scroll_panel.get_offset() >= -20
|
||||
|
||||
2
third_party/libyuv/.gitignore
vendored
2
third_party/libyuv/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
/libyuv/
|
||||
!*.a
|
||||
BIN
third_party/libyuv/Darwin/lib/libyuv.a
LFS
vendored
BIN
third_party/libyuv/Darwin/lib/libyuv.a
LFS
vendored
Binary file not shown.
29
third_party/libyuv/LICENSE
vendored
29
third_party/libyuv/LICENSE
vendored
@@ -1,29 +0,0 @@
|
||||
Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of Google nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
1
third_party/libyuv/aarch64
vendored
1
third_party/libyuv/aarch64
vendored
@@ -1 +0,0 @@
|
||||
larch64/
|
||||
37
third_party/libyuv/build.sh
vendored
37
third_party/libyuv/build.sh
vendored
@@ -1,37 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
export SOURCE_DATE_EPOCH=0
|
||||
export ZERO_AR_DATE=1
|
||||
|
||||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
|
||||
|
||||
ARCHNAME=$(uname -m)
|
||||
if [ -f /TICI ]; then
|
||||
ARCHNAME="larch64"
|
||||
fi
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
ARCHNAME="Darwin"
|
||||
fi
|
||||
|
||||
cd $DIR
|
||||
if [ ! -d libyuv ]; then
|
||||
git clone --single-branch https://chromium.googlesource.com/libyuv/libyuv
|
||||
fi
|
||||
|
||||
cd libyuv
|
||||
git checkout 4a14cb2e81235ecd656e799aecaaf139db8ce4a2
|
||||
|
||||
# build
|
||||
cmake .
|
||||
make -j$(nproc)
|
||||
|
||||
INSTALL_DIR="$DIR/$ARCHNAME"
|
||||
rm -rf $INSTALL_DIR
|
||||
mkdir -p $INSTALL_DIR
|
||||
|
||||
rm -rf $DIR/include
|
||||
mkdir -p $INSTALL_DIR/lib
|
||||
cp $DIR/libyuv/libyuv.a $INSTALL_DIR/lib
|
||||
cp -r $DIR/libyuv/include $DIR
|
||||
32
third_party/libyuv/include/libyuv.h
vendored
32
third_party/libyuv/include/libyuv.h
vendored
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_H_
|
||||
#define INCLUDE_LIBYUV_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
#include "libyuv/compare.h"
|
||||
#include "libyuv/convert.h"
|
||||
#include "libyuv/convert_argb.h"
|
||||
#include "libyuv/convert_from.h"
|
||||
#include "libyuv/convert_from_argb.h"
|
||||
#include "libyuv/cpu_id.h"
|
||||
#include "libyuv/mjpeg_decoder.h"
|
||||
#include "libyuv/planar_functions.h"
|
||||
#include "libyuv/rotate.h"
|
||||
#include "libyuv/rotate_argb.h"
|
||||
#include "libyuv/row.h"
|
||||
#include "libyuv/scale.h"
|
||||
#include "libyuv/scale_argb.h"
|
||||
#include "libyuv/scale_row.h"
|
||||
#include "libyuv/version.h"
|
||||
#include "libyuv/video_common.h"
|
||||
|
||||
#endif // INCLUDE_LIBYUV_H_
|
||||
118
third_party/libyuv/include/libyuv/basic_types.h
vendored
118
third_party/libyuv/include/libyuv/basic_types.h
vendored
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_BASIC_TYPES_H_
|
||||
#define INCLUDE_LIBYUV_BASIC_TYPES_H_
|
||||
|
||||
#include <stddef.h> // for NULL, size_t
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1600)
|
||||
#include <sys/types.h> // for uintptr_t on x86
|
||||
#else
|
||||
#include <stdint.h> // for uintptr_t
|
||||
#endif
|
||||
|
||||
#ifndef GG_LONGLONG
|
||||
#ifndef INT_TYPES_DEFINED
|
||||
#define INT_TYPES_DEFINED
|
||||
#ifdef COMPILER_MSVC
|
||||
typedef unsigned __int64 uint64;
|
||||
typedef __int64 int64;
|
||||
#ifndef INT64_C
|
||||
#define INT64_C(x) x ## I64
|
||||
#endif
|
||||
#ifndef UINT64_C
|
||||
#define UINT64_C(x) x ## UI64
|
||||
#endif
|
||||
#define INT64_F "I64"
|
||||
#else // COMPILER_MSVC
|
||||
#if defined(__LP64__) && !defined(__OpenBSD__) && !defined(__APPLE__)
|
||||
typedef unsigned long uint64; // NOLINT
|
||||
typedef long int64; // NOLINT
|
||||
#ifndef INT64_C
|
||||
#define INT64_C(x) x ## L
|
||||
#endif
|
||||
#ifndef UINT64_C
|
||||
#define UINT64_C(x) x ## UL
|
||||
#endif
|
||||
#define INT64_F "l"
|
||||
#else // defined(__LP64__) && !defined(__OpenBSD__) && !defined(__APPLE__)
|
||||
typedef unsigned long long uint64; // NOLINT
|
||||
typedef long long int64; // NOLINT
|
||||
#ifndef INT64_C
|
||||
#define INT64_C(x) x ## LL
|
||||
#endif
|
||||
#ifndef UINT64_C
|
||||
#define UINT64_C(x) x ## ULL
|
||||
#endif
|
||||
#define INT64_F "ll"
|
||||
#endif // __LP64__
|
||||
#endif // COMPILER_MSVC
|
||||
typedef unsigned int uint32;
|
||||
typedef int int32;
|
||||
typedef unsigned short uint16; // NOLINT
|
||||
typedef short int16; // NOLINT
|
||||
typedef unsigned char uint8;
|
||||
typedef signed char int8;
|
||||
#endif // INT_TYPES_DEFINED
|
||||
#endif // GG_LONGLONG
|
||||
|
||||
// Detect compiler is for x86 or x64.
|
||||
#if defined(__x86_64__) || defined(_M_X64) || \
|
||||
defined(__i386__) || defined(_M_IX86)
|
||||
#define CPU_X86 1
|
||||
#endif
|
||||
// Detect compiler is for ARM.
|
||||
#if defined(__arm__) || defined(_M_ARM)
|
||||
#define CPU_ARM 1
|
||||
#endif
|
||||
|
||||
#ifndef ALIGNP
|
||||
#ifdef __cplusplus
|
||||
#define ALIGNP(p, t) \
|
||||
(reinterpret_cast<uint8*>(((reinterpret_cast<uintptr_t>(p) + \
|
||||
((t) - 1)) & ~((t) - 1))))
|
||||
#else
|
||||
#define ALIGNP(p, t) \
|
||||
((uint8*)((((uintptr_t)(p) + ((t) - 1)) & ~((t) - 1)))) /* NOLINT */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(LIBYUV_API)
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#if defined(LIBYUV_BUILDING_SHARED_LIBRARY)
|
||||
#define LIBYUV_API __declspec(dllexport)
|
||||
#elif defined(LIBYUV_USING_SHARED_LIBRARY)
|
||||
#define LIBYUV_API __declspec(dllimport)
|
||||
#else
|
||||
#define LIBYUV_API
|
||||
#endif // LIBYUV_BUILDING_SHARED_LIBRARY
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__APPLE__) && \
|
||||
(defined(LIBYUV_BUILDING_SHARED_LIBRARY) || \
|
||||
defined(LIBYUV_USING_SHARED_LIBRARY))
|
||||
#define LIBYUV_API __attribute__ ((visibility ("default")))
|
||||
#else
|
||||
#define LIBYUV_API
|
||||
#endif // __GNUC__
|
||||
#endif // LIBYUV_API
|
||||
|
||||
#define LIBYUV_BOOL int
|
||||
#define LIBYUV_FALSE 0
|
||||
#define LIBYUV_TRUE 1
|
||||
|
||||
// Visual C x86 or GCC little endian.
|
||||
#if defined(__x86_64__) || defined(_M_X64) || \
|
||||
defined(__i386__) || defined(_M_IX86) || \
|
||||
defined(__arm__) || defined(_M_ARM) || \
|
||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
#define LIBYUV_LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_BASIC_TYPES_H_
|
||||
78
third_party/libyuv/include/libyuv/compare.h
vendored
78
third_party/libyuv/include/libyuv/compare.h
vendored
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_COMPARE_H_
|
||||
#define INCLUDE_LIBYUV_COMPARE_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Compute a hash for specified memory. Seed of 5381 recommended.
|
||||
LIBYUV_API
|
||||
uint32 HashDjb2(const uint8* src, uint64 count, uint32 seed);
|
||||
|
||||
// Scan an opaque argb image and return fourcc based on alpha offset.
|
||||
// Returns FOURCC_ARGB, FOURCC_BGRA, or 0 if unknown.
|
||||
LIBYUV_API
|
||||
uint32 ARGBDetect(const uint8* argb, int stride_argb, int width, int height);
|
||||
|
||||
// Sum Square Error - used to compute Mean Square Error or PSNR.
|
||||
LIBYUV_API
|
||||
uint64 ComputeSumSquareError(const uint8* src_a,
|
||||
const uint8* src_b, int count);
|
||||
|
||||
LIBYUV_API
|
||||
uint64 ComputeSumSquareErrorPlane(const uint8* src_a, int stride_a,
|
||||
const uint8* src_b, int stride_b,
|
||||
int width, int height);
|
||||
|
||||
static const int kMaxPsnr = 128;
|
||||
|
||||
LIBYUV_API
|
||||
double SumSquareErrorToPsnr(uint64 sse, uint64 count);
|
||||
|
||||
LIBYUV_API
|
||||
double CalcFramePsnr(const uint8* src_a, int stride_a,
|
||||
const uint8* src_b, int stride_b,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
double I420Psnr(const uint8* src_y_a, int stride_y_a,
|
||||
const uint8* src_u_a, int stride_u_a,
|
||||
const uint8* src_v_a, int stride_v_a,
|
||||
const uint8* src_y_b, int stride_y_b,
|
||||
const uint8* src_u_b, int stride_u_b,
|
||||
const uint8* src_v_b, int stride_v_b,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
double CalcFrameSsim(const uint8* src_a, int stride_a,
|
||||
const uint8* src_b, int stride_b,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
double I420Ssim(const uint8* src_y_a, int stride_y_a,
|
||||
const uint8* src_u_a, int stride_u_a,
|
||||
const uint8* src_v_a, int stride_v_a,
|
||||
const uint8* src_y_b, int stride_y_b,
|
||||
const uint8* src_u_b, int stride_u_b,
|
||||
const uint8* src_v_b, int stride_v_b,
|
||||
int width, int height);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace libyuv
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_COMPARE_H_
|
||||
84
third_party/libyuv/include/libyuv/compare_row.h
vendored
84
third_party/libyuv/include/libyuv/compare_row.h
vendored
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_COMPARE_ROW_H_
|
||||
#define INCLUDE_LIBYUV_COMPARE_ROW_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__pnacl__) || defined(__CLR_VER) || \
|
||||
(defined(__i386__) && !defined(__SSE2__))
|
||||
#define LIBYUV_DISABLE_X86
|
||||
#endif
|
||||
// MemorySanitizer does not support assembly code yet. http://crbug.com/344505
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#define LIBYUV_DISABLE_X86
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Visual C 2012 required for AVX2.
|
||||
#if defined(_M_IX86) && !defined(__clang__) && \
|
||||
defined(_MSC_VER) && _MSC_VER >= 1700
|
||||
#define VISUALC_HAS_AVX2 1
|
||||
#endif // VisualStudio >= 2012
|
||||
|
||||
// clang >= 3.4.0 required for AVX2.
|
||||
#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__))
|
||||
#if (__clang_major__ > 3) || (__clang_major__ == 3 && (__clang_minor__ >= 4))
|
||||
#define CLANG_HAS_AVX2 1
|
||||
#endif // clang >= 3.4
|
||||
#endif // __clang__
|
||||
|
||||
#if !defined(LIBYUV_DISABLE_X86) && \
|
||||
defined(_M_IX86) && (defined(VISUALC_HAS_AVX2) || defined(CLANG_HAS_AVX2))
|
||||
#define HAS_HASHDJB2_AVX2
|
||||
#endif
|
||||
|
||||
// The following are available for Visual C and GCC:
|
||||
#if !defined(LIBYUV_DISABLE_X86) && \
|
||||
(defined(__x86_64__) || (defined(__i386__) || defined(_M_IX86)))
|
||||
#define HAS_HASHDJB2_SSE41
|
||||
#define HAS_SUMSQUAREERROR_SSE2
|
||||
#endif
|
||||
|
||||
// The following are available for Visual C and clangcl 32 bit:
|
||||
#if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && \
|
||||
(defined(VISUALC_HAS_AVX2) || defined(CLANG_HAS_AVX2))
|
||||
#define HAS_HASHDJB2_AVX2
|
||||
#define HAS_SUMSQUAREERROR_AVX2
|
||||
#endif
|
||||
|
||||
// The following are available for Neon:
|
||||
#if !defined(LIBYUV_DISABLE_NEON) && \
|
||||
(defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__))
|
||||
#define HAS_SUMSQUAREERROR_NEON
|
||||
#endif
|
||||
|
||||
uint32 SumSquareError_C(const uint8* src_a, const uint8* src_b, int count);
|
||||
uint32 SumSquareError_SSE2(const uint8* src_a, const uint8* src_b, int count);
|
||||
uint32 SumSquareError_AVX2(const uint8* src_a, const uint8* src_b, int count);
|
||||
uint32 SumSquareError_NEON(const uint8* src_a, const uint8* src_b, int count);
|
||||
|
||||
uint32 HashDjb2_C(const uint8* src, int count, uint32 seed);
|
||||
uint32 HashDjb2_SSE41(const uint8* src, int count, uint32 seed);
|
||||
uint32 HashDjb2_AVX2(const uint8* src, int count, uint32 seed);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace libyuv
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_COMPARE_ROW_H_
|
||||
259
third_party/libyuv/include/libyuv/convert.h
vendored
259
third_party/libyuv/include/libyuv/convert.h
vendored
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_CONVERT_H_
|
||||
#define INCLUDE_LIBYUV_CONVERT_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
|
||||
#include "libyuv/rotate.h" // For enum RotationMode.
|
||||
|
||||
// TODO(fbarchard): fix WebRTC source to include following libyuv headers:
|
||||
#include "libyuv/convert_argb.h" // For WebRTC I420ToARGB. b/620
|
||||
#include "libyuv/convert_from.h" // For WebRTC ConvertFromI420. b/620
|
||||
#include "libyuv/planar_functions.h" // For WebRTC I420Rect, CopyPlane. b/618
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Convert I444 to I420.
|
||||
LIBYUV_API
|
||||
int I444ToI420(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert I422 to I420.
|
||||
LIBYUV_API
|
||||
int I422ToI420(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert I411 to I420.
|
||||
LIBYUV_API
|
||||
int I411ToI420(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Copy I420 to I420.
|
||||
#define I420ToI420 I420Copy
|
||||
LIBYUV_API
|
||||
int I420Copy(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert I400 (grey) to I420.
|
||||
LIBYUV_API
|
||||
int I400ToI420(const uint8* src_y, int src_stride_y,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
#define J400ToJ420 I400ToI420
|
||||
|
||||
// Convert NV12 to I420.
|
||||
LIBYUV_API
|
||||
int NV12ToI420(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_uv, int src_stride_uv,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert NV21 to I420.
|
||||
LIBYUV_API
|
||||
int NV21ToI420(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_vu, int src_stride_vu,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert YUY2 to I420.
|
||||
LIBYUV_API
|
||||
int YUY2ToI420(const uint8* src_yuy2, int src_stride_yuy2,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert UYVY to I420.
|
||||
LIBYUV_API
|
||||
int UYVYToI420(const uint8* src_uyvy, int src_stride_uyvy,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert M420 to I420.
|
||||
LIBYUV_API
|
||||
int M420ToI420(const uint8* src_m420, int src_stride_m420,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert Android420 to I420.
|
||||
LIBYUV_API
|
||||
int Android420ToI420(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
int pixel_stride_uv,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// ARGB little endian (bgra in memory) to I420.
|
||||
LIBYUV_API
|
||||
int ARGBToI420(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// BGRA little endian (argb in memory) to I420.
|
||||
LIBYUV_API
|
||||
int BGRAToI420(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// ABGR little endian (rgba in memory) to I420.
|
||||
LIBYUV_API
|
||||
int ABGRToI420(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// RGBA little endian (abgr in memory) to I420.
|
||||
LIBYUV_API
|
||||
int RGBAToI420(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// RGB little endian (bgr in memory) to I420.
|
||||
LIBYUV_API
|
||||
int RGB24ToI420(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// RGB big endian (rgb in memory) to I420.
|
||||
LIBYUV_API
|
||||
int RAWToI420(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// RGB16 (RGBP fourcc) little endian to I420.
|
||||
LIBYUV_API
|
||||
int RGB565ToI420(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// RGB15 (RGBO fourcc) little endian to I420.
|
||||
LIBYUV_API
|
||||
int ARGB1555ToI420(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// RGB12 (R444 fourcc) little endian to I420.
|
||||
LIBYUV_API
|
||||
int ARGB4444ToI420(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
#ifdef HAVE_JPEG
|
||||
// src_width/height provided by capture.
|
||||
// dst_width/height for clipping determine final size.
|
||||
LIBYUV_API
|
||||
int MJPGToI420(const uint8* sample, size_t sample_size,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int src_width, int src_height,
|
||||
int dst_width, int dst_height);
|
||||
|
||||
// Query size of MJPG in pixels.
|
||||
LIBYUV_API
|
||||
int MJPGSize(const uint8* sample, size_t sample_size,
|
||||
int* width, int* height);
|
||||
#endif
|
||||
|
||||
// Convert camera sample to I420 with cropping, rotation and vertical flip.
|
||||
// "src_size" is needed to parse MJPG.
|
||||
// "dst_stride_y" number of bytes in a row of the dst_y plane.
|
||||
// Normally this would be the same as dst_width, with recommended alignment
|
||||
// to 16 bytes for better efficiency.
|
||||
// If rotation of 90 or 270 is used, stride is affected. The caller should
|
||||
// allocate the I420 buffer according to rotation.
|
||||
// "dst_stride_u" number of bytes in a row of the dst_u plane.
|
||||
// Normally this would be the same as (dst_width + 1) / 2, with
|
||||
// recommended alignment to 16 bytes for better efficiency.
|
||||
// If rotation of 90 or 270 is used, stride is affected.
|
||||
// "crop_x" and "crop_y" are starting position for cropping.
|
||||
// To center, crop_x = (src_width - dst_width) / 2
|
||||
// crop_y = (src_height - dst_height) / 2
|
||||
// "src_width" / "src_height" is size of src_frame in pixels.
|
||||
// "src_height" can be negative indicating a vertically flipped image source.
|
||||
// "crop_width" / "crop_height" is the size to crop the src to.
|
||||
// Must be less than or equal to src_width/src_height
|
||||
// Cropping parameters are pre-rotation.
|
||||
// "rotation" can be 0, 90, 180 or 270.
|
||||
// "format" is a fourcc. ie 'I420', 'YUY2'
|
||||
// Returns 0 for successful; -1 for invalid parameter. Non-zero for failure.
|
||||
LIBYUV_API
|
||||
int ConvertToI420(const uint8* src_frame, size_t src_size,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int crop_x, int crop_y,
|
||||
int src_width, int src_height,
|
||||
int crop_width, int crop_height,
|
||||
enum RotationMode rotation,
|
||||
uint32 format);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace libyuv
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_CONVERT_H_
|
||||
319
third_party/libyuv/include/libyuv/convert_argb.h
vendored
319
third_party/libyuv/include/libyuv/convert_argb.h
vendored
@@ -1,319 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_CONVERT_ARGB_H_
|
||||
#define INCLUDE_LIBYUV_CONVERT_ARGB_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
|
||||
#include "libyuv/rotate.h" // For enum RotationMode.
|
||||
|
||||
// TODO(fbarchard): This set of functions should exactly match convert.h
|
||||
// TODO(fbarchard): Add tests. Create random content of right size and convert
|
||||
// with C vs Opt and or to I420 and compare.
|
||||
// TODO(fbarchard): Some of these functions lack parameter setting.
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Alias.
|
||||
#define ARGBToARGB ARGBCopy
|
||||
|
||||
// Copy ARGB to ARGB.
|
||||
LIBYUV_API
|
||||
int ARGBCopy(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert I420 to ARGB.
|
||||
LIBYUV_API
|
||||
int I420ToARGB(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Duplicate prototype for function in convert_from.h for remoting.
|
||||
LIBYUV_API
|
||||
int I420ToABGR(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert I422 to ARGB.
|
||||
LIBYUV_API
|
||||
int I422ToARGB(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert I444 to ARGB.
|
||||
LIBYUV_API
|
||||
int I444ToARGB(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert J444 to ARGB.
|
||||
LIBYUV_API
|
||||
int J444ToARGB(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert I444 to ABGR.
|
||||
LIBYUV_API
|
||||
int I444ToABGR(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_abgr, int dst_stride_abgr,
|
||||
int width, int height);
|
||||
|
||||
// Convert I411 to ARGB.
|
||||
LIBYUV_API
|
||||
int I411ToARGB(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert I420 with Alpha to preattenuated ARGB.
|
||||
LIBYUV_API
|
||||
int I420AlphaToARGB(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
const uint8* src_a, int src_stride_a,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height, int attenuate);
|
||||
|
||||
// Convert I420 with Alpha to preattenuated ABGR.
|
||||
LIBYUV_API
|
||||
int I420AlphaToABGR(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
const uint8* src_a, int src_stride_a,
|
||||
uint8* dst_abgr, int dst_stride_abgr,
|
||||
int width, int height, int attenuate);
|
||||
|
||||
// Convert I400 (grey) to ARGB. Reverse of ARGBToI400.
|
||||
LIBYUV_API
|
||||
int I400ToARGB(const uint8* src_y, int src_stride_y,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert J400 (jpeg grey) to ARGB.
|
||||
LIBYUV_API
|
||||
int J400ToARGB(const uint8* src_y, int src_stride_y,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Alias.
|
||||
#define YToARGB I400ToARGB
|
||||
|
||||
// Convert NV12 to ARGB.
|
||||
LIBYUV_API
|
||||
int NV12ToARGB(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_uv, int src_stride_uv,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert NV21 to ARGB.
|
||||
LIBYUV_API
|
||||
int NV21ToARGB(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_vu, int src_stride_vu,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert M420 to ARGB.
|
||||
LIBYUV_API
|
||||
int M420ToARGB(const uint8* src_m420, int src_stride_m420,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert YUY2 to ARGB.
|
||||
LIBYUV_API
|
||||
int YUY2ToARGB(const uint8* src_yuy2, int src_stride_yuy2,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert UYVY to ARGB.
|
||||
LIBYUV_API
|
||||
int UYVYToARGB(const uint8* src_uyvy, int src_stride_uyvy,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert J420 to ARGB.
|
||||
LIBYUV_API
|
||||
int J420ToARGB(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert J422 to ARGB.
|
||||
LIBYUV_API
|
||||
int J422ToARGB(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert J420 to ABGR.
|
||||
LIBYUV_API
|
||||
int J420ToABGR(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_abgr, int dst_stride_abgr,
|
||||
int width, int height);
|
||||
|
||||
// Convert J422 to ABGR.
|
||||
LIBYUV_API
|
||||
int J422ToABGR(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_abgr, int dst_stride_abgr,
|
||||
int width, int height);
|
||||
|
||||
// Convert H420 to ARGB.
|
||||
LIBYUV_API
|
||||
int H420ToARGB(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert H422 to ARGB.
|
||||
LIBYUV_API
|
||||
int H422ToARGB(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert H420 to ABGR.
|
||||
LIBYUV_API
|
||||
int H420ToABGR(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_abgr, int dst_stride_abgr,
|
||||
int width, int height);
|
||||
|
||||
// Convert H422 to ABGR.
|
||||
LIBYUV_API
|
||||
int H422ToABGR(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_abgr, int dst_stride_abgr,
|
||||
int width, int height);
|
||||
|
||||
// BGRA little endian (argb in memory) to ARGB.
|
||||
LIBYUV_API
|
||||
int BGRAToARGB(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// ABGR little endian (rgba in memory) to ARGB.
|
||||
LIBYUV_API
|
||||
int ABGRToARGB(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// RGBA little endian (abgr in memory) to ARGB.
|
||||
LIBYUV_API
|
||||
int RGBAToARGB(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Deprecated function name.
|
||||
#define BG24ToARGB RGB24ToARGB
|
||||
|
||||
// RGB little endian (bgr in memory) to ARGB.
|
||||
LIBYUV_API
|
||||
int RGB24ToARGB(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// RGB big endian (rgb in memory) to ARGB.
|
||||
LIBYUV_API
|
||||
int RAWToARGB(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// RGB16 (RGBP fourcc) little endian to ARGB.
|
||||
LIBYUV_API
|
||||
int RGB565ToARGB(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// RGB15 (RGBO fourcc) little endian to ARGB.
|
||||
LIBYUV_API
|
||||
int ARGB1555ToARGB(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// RGB12 (R444 fourcc) little endian to ARGB.
|
||||
LIBYUV_API
|
||||
int ARGB4444ToARGB(const uint8* src_frame, int src_stride_frame,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
#ifdef HAVE_JPEG
|
||||
// src_width/height provided by capture
|
||||
// dst_width/height for clipping determine final size.
|
||||
LIBYUV_API
|
||||
int MJPGToARGB(const uint8* sample, size_t sample_size,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int src_width, int src_height,
|
||||
int dst_width, int dst_height);
|
||||
#endif
|
||||
|
||||
// Convert camera sample to ARGB with cropping, rotation and vertical flip.
|
||||
// "src_size" is needed to parse MJPG.
|
||||
// "dst_stride_argb" number of bytes in a row of the dst_argb plane.
|
||||
// Normally this would be the same as dst_width, with recommended alignment
|
||||
// to 16 bytes for better efficiency.
|
||||
// If rotation of 90 or 270 is used, stride is affected. The caller should
|
||||
// allocate the I420 buffer according to rotation.
|
||||
// "dst_stride_u" number of bytes in a row of the dst_u plane.
|
||||
// Normally this would be the same as (dst_width + 1) / 2, with
|
||||
// recommended alignment to 16 bytes for better efficiency.
|
||||
// If rotation of 90 or 270 is used, stride is affected.
|
||||
// "crop_x" and "crop_y" are starting position for cropping.
|
||||
// To center, crop_x = (src_width - dst_width) / 2
|
||||
// crop_y = (src_height - dst_height) / 2
|
||||
// "src_width" / "src_height" is size of src_frame in pixels.
|
||||
// "src_height" can be negative indicating a vertically flipped image source.
|
||||
// "crop_width" / "crop_height" is the size to crop the src to.
|
||||
// Must be less than or equal to src_width/src_height
|
||||
// Cropping parameters are pre-rotation.
|
||||
// "rotation" can be 0, 90, 180 or 270.
|
||||
// "format" is a fourcc. ie 'I420', 'YUY2'
|
||||
// Returns 0 for successful; -1 for invalid parameter. Non-zero for failure.
|
||||
LIBYUV_API
|
||||
int ConvertToARGB(const uint8* src_frame, size_t src_size,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int crop_x, int crop_y,
|
||||
int src_width, int src_height,
|
||||
int crop_width, int crop_height,
|
||||
enum RotationMode rotation,
|
||||
uint32 format);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace libyuv
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_CONVERT_ARGB_H_
|
||||
179
third_party/libyuv/include/libyuv/convert_from.h
vendored
179
third_party/libyuv/include/libyuv/convert_from.h
vendored
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_CONVERT_FROM_H_
|
||||
#define INCLUDE_LIBYUV_CONVERT_FROM_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
#include "libyuv/rotate.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// See Also convert.h for conversions from formats to I420.
|
||||
|
||||
// I420Copy in convert to I420ToI420.
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToI422(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToI444(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToI411(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Copy to I400. Source can be I420, I422, I444, I400, NV12 or NV21.
|
||||
LIBYUV_API
|
||||
int I400Copy(const uint8* src_y, int src_stride_y,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToNV12(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_uv, int dst_stride_uv,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToNV21(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_vu, int dst_stride_vu,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToYUY2(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_frame, int dst_stride_frame,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToUYVY(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_frame, int dst_stride_frame,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToARGB(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToBGRA(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToABGR(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToRGBA(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_rgba, int dst_stride_rgba,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToRGB24(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_frame, int dst_stride_frame,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToRAW(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_frame, int dst_stride_frame,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToRGB565(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_frame, int dst_stride_frame,
|
||||
int width, int height);
|
||||
|
||||
// Convert I420 To RGB565 with 4x4 dither matrix (16 bytes).
|
||||
// Values in dither matrix from 0 to 7 recommended.
|
||||
// The order of the dither matrix is first byte is upper left.
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToRGB565Dither(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_frame, int dst_stride_frame,
|
||||
const uint8* dither4x4, int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToARGB1555(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_frame, int dst_stride_frame,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int I420ToARGB4444(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_frame, int dst_stride_frame,
|
||||
int width, int height);
|
||||
|
||||
// Convert I420 to specified format.
|
||||
// "dst_sample_stride" is bytes in a row for the destination. Pass 0 if the
|
||||
// buffer has contiguous rows. Can be negative. A multiple of 16 is optimal.
|
||||
LIBYUV_API
|
||||
int ConvertFromI420(const uint8* y, int y_stride,
|
||||
const uint8* u, int u_stride,
|
||||
const uint8* v, int v_stride,
|
||||
uint8* dst_sample, int dst_sample_stride,
|
||||
int width, int height,
|
||||
uint32 format);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace libyuv
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_CONVERT_FROM_H_
|
||||
@@ -1,190 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_CONVERT_FROM_ARGB_H_
|
||||
#define INCLUDE_LIBYUV_CONVERT_FROM_ARGB_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Copy ARGB to ARGB.
|
||||
#define ARGBToARGB ARGBCopy
|
||||
LIBYUV_API
|
||||
int ARGBCopy(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To BGRA.
|
||||
LIBYUV_API
|
||||
int ARGBToBGRA(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_bgra, int dst_stride_bgra,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To ABGR.
|
||||
LIBYUV_API
|
||||
int ARGBToABGR(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_abgr, int dst_stride_abgr,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To RGBA.
|
||||
LIBYUV_API
|
||||
int ARGBToRGBA(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_rgba, int dst_stride_rgba,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To RGB24.
|
||||
LIBYUV_API
|
||||
int ARGBToRGB24(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_rgb24, int dst_stride_rgb24,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To RAW.
|
||||
LIBYUV_API
|
||||
int ARGBToRAW(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_rgb, int dst_stride_rgb,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To RGB565.
|
||||
LIBYUV_API
|
||||
int ARGBToRGB565(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_rgb565, int dst_stride_rgb565,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To RGB565 with 4x4 dither matrix (16 bytes).
|
||||
// Values in dither matrix from 0 to 7 recommended.
|
||||
// The order of the dither matrix is first byte is upper left.
|
||||
// TODO(fbarchard): Consider pointer to 2d array for dither4x4.
|
||||
// const uint8(*dither)[4][4];
|
||||
LIBYUV_API
|
||||
int ARGBToRGB565Dither(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_rgb565, int dst_stride_rgb565,
|
||||
const uint8* dither4x4, int width, int height);
|
||||
|
||||
// Convert ARGB To ARGB1555.
|
||||
LIBYUV_API
|
||||
int ARGBToARGB1555(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb1555, int dst_stride_argb1555,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To ARGB4444.
|
||||
LIBYUV_API
|
||||
int ARGBToARGB4444(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb4444, int dst_stride_argb4444,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To I444.
|
||||
LIBYUV_API
|
||||
int ARGBToI444(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To I422.
|
||||
LIBYUV_API
|
||||
int ARGBToI422(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To I420. (also in convert.h)
|
||||
LIBYUV_API
|
||||
int ARGBToI420(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB to J420. (JPeg full range I420).
|
||||
LIBYUV_API
|
||||
int ARGBToJ420(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_yj, int dst_stride_yj,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB to J422.
|
||||
LIBYUV_API
|
||||
int ARGBToJ422(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_yj, int dst_stride_yj,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To I411.
|
||||
LIBYUV_API
|
||||
int ARGBToI411(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB to J400. (JPeg full range).
|
||||
LIBYUV_API
|
||||
int ARGBToJ400(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_yj, int dst_stride_yj,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB to I400.
|
||||
LIBYUV_API
|
||||
int ARGBToI400(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB to G. (Reverse of J400toARGB, which replicates G back to ARGB)
|
||||
LIBYUV_API
|
||||
int ARGBToG(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_g, int dst_stride_g,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To NV12.
|
||||
LIBYUV_API
|
||||
int ARGBToNV12(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_uv, int dst_stride_uv,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To NV21.
|
||||
LIBYUV_API
|
||||
int ARGBToNV21(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_vu, int dst_stride_vu,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To NV21.
|
||||
LIBYUV_API
|
||||
int ARGBToNV21(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_vu, int dst_stride_vu,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To YUY2.
|
||||
LIBYUV_API
|
||||
int ARGBToYUY2(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_yuy2, int dst_stride_yuy2,
|
||||
int width, int height);
|
||||
|
||||
// Convert ARGB To UYVY.
|
||||
LIBYUV_API
|
||||
int ARGBToUYVY(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_uyvy, int dst_stride_uyvy,
|
||||
int width, int height);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace libyuv
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_CONVERT_FROM_ARGB_H_
|
||||
81
third_party/libyuv/include/libyuv/cpu_id.h
vendored
81
third_party/libyuv/include/libyuv/cpu_id.h
vendored
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_CPU_ID_H_
|
||||
#define INCLUDE_LIBYUV_CPU_ID_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Internal flag to indicate cpuid requires initialization.
|
||||
static const int kCpuInitialized = 0x1;
|
||||
|
||||
// These flags are only valid on ARM processors.
|
||||
static const int kCpuHasARM = 0x2;
|
||||
static const int kCpuHasNEON = 0x4;
|
||||
// 0x8 reserved for future ARM flag.
|
||||
|
||||
// These flags are only valid on x86 processors.
|
||||
static const int kCpuHasX86 = 0x10;
|
||||
static const int kCpuHasSSE2 = 0x20;
|
||||
static const int kCpuHasSSSE3 = 0x40;
|
||||
static const int kCpuHasSSE41 = 0x80;
|
||||
static const int kCpuHasSSE42 = 0x100;
|
||||
static const int kCpuHasAVX = 0x200;
|
||||
static const int kCpuHasAVX2 = 0x400;
|
||||
static const int kCpuHasERMS = 0x800;
|
||||
static const int kCpuHasFMA3 = 0x1000;
|
||||
static const int kCpuHasAVX3 = 0x2000;
|
||||
// 0x2000, 0x4000, 0x8000 reserved for future X86 flags.
|
||||
|
||||
// These flags are only valid on MIPS processors.
|
||||
static const int kCpuHasMIPS = 0x10000;
|
||||
static const int kCpuHasDSPR2 = 0x20000;
|
||||
static const int kCpuHasMSA = 0x40000;
|
||||
|
||||
// Internal function used to auto-init.
|
||||
LIBYUV_API
|
||||
int InitCpuFlags(void);
|
||||
|
||||
// Internal function for parsing /proc/cpuinfo.
|
||||
LIBYUV_API
|
||||
int ArmCpuCaps(const char* cpuinfo_name);
|
||||
|
||||
// Detect CPU has SSE2 etc.
|
||||
// Test_flag parameter should be one of kCpuHas constants above.
|
||||
// returns non-zero if instruction set is detected
|
||||
static __inline int TestCpuFlag(int test_flag) {
|
||||
LIBYUV_API extern int cpu_info_;
|
||||
return (!cpu_info_ ? InitCpuFlags() : cpu_info_) & test_flag;
|
||||
}
|
||||
|
||||
// For testing, allow CPU flags to be disabled.
|
||||
// ie MaskCpuFlags(~kCpuHasSSSE3) to disable SSSE3.
|
||||
// MaskCpuFlags(-1) to enable all cpu specific optimizations.
|
||||
// MaskCpuFlags(1) to disable all cpu specific optimizations.
|
||||
LIBYUV_API
|
||||
void MaskCpuFlags(int enable_flags);
|
||||
|
||||
// Low level cpuid for X86. Returns zeros on other CPUs.
|
||||
// eax is the info type that you want.
|
||||
// ecx is typically the cpu number, and should normally be zero.
|
||||
LIBYUV_API
|
||||
void CpuId(uint32 eax, uint32 ecx, uint32* cpu_info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace libyuv
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_CPU_ID_H_
|
||||
76
third_party/libyuv/include/libyuv/macros_msa.h
vendored
76
third_party/libyuv/include/libyuv/macros_msa.h
vendored
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_MACROS_MSA_H_
|
||||
#define INCLUDE_LIBYUV_MACROS_MSA_H_
|
||||
|
||||
#if !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa)
|
||||
#include <stdint.h>
|
||||
#include <msa.h>
|
||||
|
||||
#define LD_B(RTYPE, psrc) *((RTYPE*)(psrc)) /* NOLINT */
|
||||
#define LD_UB(...) LD_B(v16u8, __VA_ARGS__)
|
||||
|
||||
#define ST_B(RTYPE, in, pdst) *((RTYPE*)(pdst)) = (in) /* NOLINT */
|
||||
#define ST_UB(...) ST_B(v16u8, __VA_ARGS__)
|
||||
|
||||
/* Description : Load two vectors with 16 'byte' sized elements
|
||||
Arguments : Inputs - psrc, stride
|
||||
Outputs - out0, out1
|
||||
Return Type - as per RTYPE
|
||||
Details : Load 16 byte elements in 'out0' from (psrc)
|
||||
Load 16 byte elements in 'out1' from (psrc + stride)
|
||||
*/
|
||||
#define LD_B2(RTYPE, psrc, stride, out0, out1) { \
|
||||
out0 = LD_B(RTYPE, (psrc)); \
|
||||
out1 = LD_B(RTYPE, (psrc) + stride); \
|
||||
}
|
||||
#define LD_UB2(...) LD_B2(v16u8, __VA_ARGS__)
|
||||
|
||||
#define LD_B4(RTYPE, psrc, stride, out0, out1, out2, out3) { \
|
||||
LD_B2(RTYPE, (psrc), stride, out0, out1); \
|
||||
LD_B2(RTYPE, (psrc) + 2 * stride , stride, out2, out3); \
|
||||
}
|
||||
#define LD_UB4(...) LD_B4(v16u8, __VA_ARGS__)
|
||||
|
||||
/* Description : Store two vectors with stride each having 16 'byte' sized
|
||||
elements
|
||||
Arguments : Inputs - in0, in1, pdst, stride
|
||||
Details : Store 16 byte elements from 'in0' to (pdst)
|
||||
Store 16 byte elements from 'in1' to (pdst + stride)
|
||||
*/
|
||||
#define ST_B2(RTYPE, in0, in1, pdst, stride) { \
|
||||
ST_B(RTYPE, in0, (pdst)); \
|
||||
ST_B(RTYPE, in1, (pdst) + stride); \
|
||||
}
|
||||
#define ST_UB2(...) ST_B2(v16u8, __VA_ARGS__)
|
||||
#
|
||||
#define ST_B4(RTYPE, in0, in1, in2, in3, pdst, stride) { \
|
||||
ST_B2(RTYPE, in0, in1, (pdst), stride); \
|
||||
ST_B2(RTYPE, in2, in3, (pdst) + 2 * stride, stride); \
|
||||
}
|
||||
#define ST_UB4(...) ST_B4(v16u8, __VA_ARGS__)
|
||||
#
|
||||
/* Description : Shuffle byte vector elements as per mask vector
|
||||
Arguments : Inputs - in0, in1, in2, in3, mask0, mask1
|
||||
Outputs - out0, out1
|
||||
Return Type - as per RTYPE
|
||||
Details : Byte elements from 'in0' & 'in1' are copied selectively to
|
||||
'out0' as per control vector 'mask0'
|
||||
*/
|
||||
#define VSHF_B2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1) { \
|
||||
out0 = (RTYPE) __msa_vshf_b((v16i8) mask0, (v16i8) in1, (v16i8) in0); \
|
||||
out1 = (RTYPE) __msa_vshf_b((v16i8) mask1, (v16i8) in3, (v16i8) in2); \
|
||||
}
|
||||
#define VSHF_B2_UB(...) VSHF_B2(v16u8, __VA_ARGS__)
|
||||
|
||||
#endif /* !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa) */
|
||||
|
||||
#endif // INCLUDE_LIBYUV_MACROS_MSA_H_
|
||||
192
third_party/libyuv/include/libyuv/mjpeg_decoder.h
vendored
192
third_party/libyuv/include/libyuv/mjpeg_decoder.h
vendored
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_MJPEG_DECODER_H_
|
||||
#define INCLUDE_LIBYUV_MJPEG_DECODER_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
// NOTE: For a simplified public API use convert.h MJPGToI420().
|
||||
|
||||
struct jpeg_common_struct;
|
||||
struct jpeg_decompress_struct;
|
||||
struct jpeg_source_mgr;
|
||||
|
||||
namespace libyuv {
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
LIBYUV_BOOL ValidateJpeg(const uint8* sample, size_t sample_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
static const uint32 kUnknownDataSize = 0xFFFFFFFF;
|
||||
|
||||
enum JpegSubsamplingType {
|
||||
kJpegYuv420,
|
||||
kJpegYuv422,
|
||||
kJpegYuv411,
|
||||
kJpegYuv444,
|
||||
kJpegYuv400,
|
||||
kJpegUnknown
|
||||
};
|
||||
|
||||
struct Buffer {
|
||||
const uint8* data;
|
||||
int len;
|
||||
};
|
||||
|
||||
struct BufferVector {
|
||||
Buffer* buffers;
|
||||
int len;
|
||||
int pos;
|
||||
};
|
||||
|
||||
struct SetJmpErrorMgr;
|
||||
|
||||
// MJPEG ("Motion JPEG") is a pseudo-standard video codec where the frames are
|
||||
// simply independent JPEG images with a fixed huffman table (which is omitted).
|
||||
// It is rarely used in video transmission, but is common as a camera capture
|
||||
// format, especially in Logitech devices. This class implements a decoder for
|
||||
// MJPEG frames.
|
||||
//
|
||||
// See http://tools.ietf.org/html/rfc2435
|
||||
class LIBYUV_API MJpegDecoder {
|
||||
public:
|
||||
typedef void (*CallbackFunction)(void* opaque,
|
||||
const uint8* const* data,
|
||||
const int* strides,
|
||||
int rows);
|
||||
|
||||
static const int kColorSpaceUnknown;
|
||||
static const int kColorSpaceGrayscale;
|
||||
static const int kColorSpaceRgb;
|
||||
static const int kColorSpaceYCbCr;
|
||||
static const int kColorSpaceCMYK;
|
||||
static const int kColorSpaceYCCK;
|
||||
|
||||
MJpegDecoder();
|
||||
~MJpegDecoder();
|
||||
|
||||
// Loads a new frame, reads its headers, and determines the uncompressed
|
||||
// image format.
|
||||
// Returns LIBYUV_TRUE if image looks valid and format is supported.
|
||||
// If return value is LIBYUV_TRUE, then the values for all the following
|
||||
// getters are populated.
|
||||
// src_len is the size of the compressed mjpeg frame in bytes.
|
||||
LIBYUV_BOOL LoadFrame(const uint8* src, size_t src_len);
|
||||
|
||||
// Returns width of the last loaded frame in pixels.
|
||||
int GetWidth();
|
||||
|
||||
// Returns height of the last loaded frame in pixels.
|
||||
int GetHeight();
|
||||
|
||||
// Returns format of the last loaded frame. The return value is one of the
|
||||
// kColorSpace* constants.
|
||||
int GetColorSpace();
|
||||
|
||||
// Number of color components in the color space.
|
||||
int GetNumComponents();
|
||||
|
||||
// Sample factors of the n-th component.
|
||||
int GetHorizSampFactor(int component);
|
||||
|
||||
int GetVertSampFactor(int component);
|
||||
|
||||
int GetHorizSubSampFactor(int component);
|
||||
|
||||
int GetVertSubSampFactor(int component);
|
||||
|
||||
// Public for testability.
|
||||
int GetImageScanlinesPerImcuRow();
|
||||
|
||||
// Public for testability.
|
||||
int GetComponentScanlinesPerImcuRow(int component);
|
||||
|
||||
// Width of a component in bytes.
|
||||
int GetComponentWidth(int component);
|
||||
|
||||
// Height of a component.
|
||||
int GetComponentHeight(int component);
|
||||
|
||||
// Width of a component in bytes with padding for DCTSIZE. Public for testing.
|
||||
int GetComponentStride(int component);
|
||||
|
||||
// Size of a component in bytes.
|
||||
int GetComponentSize(int component);
|
||||
|
||||
// Call this after LoadFrame() if you decide you don't want to decode it
|
||||
// after all.
|
||||
LIBYUV_BOOL UnloadFrame();
|
||||
|
||||
// Decodes the entire image into a one-buffer-per-color-component format.
|
||||
// dst_width must match exactly. dst_height must be <= to image height; if
|
||||
// less, the image is cropped. "planes" must have size equal to at least
|
||||
// GetNumComponents() and they must point to non-overlapping buffers of size
|
||||
// at least GetComponentSize(i). The pointers in planes are incremented
|
||||
// to point to after the end of the written data.
|
||||
// TODO(fbarchard): Add dst_x, dst_y to allow specific rect to be decoded.
|
||||
LIBYUV_BOOL DecodeToBuffers(uint8** planes, int dst_width, int dst_height);
|
||||
|
||||
// Decodes the entire image and passes the data via repeated calls to a
|
||||
// callback function. Each call will get the data for a whole number of
|
||||
// image scanlines.
|
||||
// TODO(fbarchard): Add dst_x, dst_y to allow specific rect to be decoded.
|
||||
LIBYUV_BOOL DecodeToCallback(CallbackFunction fn, void* opaque,
|
||||
int dst_width, int dst_height);
|
||||
|
||||
// The helper function which recognizes the jpeg sub-sampling type.
|
||||
static JpegSubsamplingType JpegSubsamplingTypeHelper(
|
||||
int* subsample_x, int* subsample_y, int number_of_components);
|
||||
|
||||
private:
|
||||
void AllocOutputBuffers(int num_outbufs);
|
||||
void DestroyOutputBuffers();
|
||||
|
||||
LIBYUV_BOOL StartDecode();
|
||||
LIBYUV_BOOL FinishDecode();
|
||||
|
||||
void SetScanlinePointers(uint8** data);
|
||||
LIBYUV_BOOL DecodeImcuRow();
|
||||
|
||||
int GetComponentScanlinePadding(int component);
|
||||
|
||||
// A buffer holding the input data for a frame.
|
||||
Buffer buf_;
|
||||
BufferVector buf_vec_;
|
||||
|
||||
jpeg_decompress_struct* decompress_struct_;
|
||||
jpeg_source_mgr* source_mgr_;
|
||||
SetJmpErrorMgr* error_mgr_;
|
||||
|
||||
// LIBYUV_TRUE iff at least one component has scanline padding. (i.e.,
|
||||
// GetComponentScanlinePadding() != 0.)
|
||||
LIBYUV_BOOL has_scanline_padding_;
|
||||
|
||||
// Temporaries used to point to scanline outputs.
|
||||
int num_outbufs_; // Outermost size of all arrays below.
|
||||
uint8*** scanlines_;
|
||||
int* scanlines_sizes_;
|
||||
// Temporary buffer used for decoding when we can't decode directly to the
|
||||
// output buffers. Large enough for just one iMCU row.
|
||||
uint8** databuf_;
|
||||
int* databuf_strides_;
|
||||
};
|
||||
|
||||
} // namespace libyuv
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // INCLUDE_LIBYUV_MJPEG_DECODER_H_
|
||||
529
third_party/libyuv/include/libyuv/planar_functions.h
vendored
529
third_party/libyuv/include/libyuv/planar_functions.h
vendored
@@ -1,529 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_PLANAR_FUNCTIONS_H_
|
||||
#define INCLUDE_LIBYUV_PLANAR_FUNCTIONS_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
|
||||
// TODO(fbarchard): Remove the following headers includes.
|
||||
#include "libyuv/convert.h"
|
||||
#include "libyuv/convert_argb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Copy a plane of data.
|
||||
LIBYUV_API
|
||||
void CopyPlane(const uint8* src_y, int src_stride_y,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
void CopyPlane_16(const uint16* src_y, int src_stride_y,
|
||||
uint16* dst_y, int dst_stride_y,
|
||||
int width, int height);
|
||||
|
||||
// Set a plane of data to a 32 bit value.
|
||||
LIBYUV_API
|
||||
void SetPlane(uint8* dst_y, int dst_stride_y,
|
||||
int width, int height,
|
||||
uint32 value);
|
||||
|
||||
// Split interleaved UV plane into separate U and V planes.
|
||||
LIBYUV_API
|
||||
void SplitUVPlane(const uint8* src_uv, int src_stride_uv,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Merge separate U and V planes into one interleaved UV plane.
|
||||
LIBYUV_API
|
||||
void MergeUVPlane(const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_uv, int dst_stride_uv,
|
||||
int width, int height);
|
||||
|
||||
// Copy I400. Supports inverting.
|
||||
LIBYUV_API
|
||||
int I400ToI400(const uint8* src_y, int src_stride_y,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
int width, int height);
|
||||
|
||||
#define J400ToJ400 I400ToI400
|
||||
|
||||
// Copy I422 to I422.
|
||||
#define I422ToI422 I422Copy
|
||||
LIBYUV_API
|
||||
int I422Copy(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Copy I444 to I444.
|
||||
#define I444ToI444 I444Copy
|
||||
LIBYUV_API
|
||||
int I444Copy(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert YUY2 to I422.
|
||||
LIBYUV_API
|
||||
int YUY2ToI422(const uint8* src_yuy2, int src_stride_yuy2,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Convert UYVY to I422.
|
||||
LIBYUV_API
|
||||
int UYVYToI422(const uint8* src_uyvy, int src_stride_uyvy,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int YUY2ToNV12(const uint8* src_yuy2, int src_stride_yuy2,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_uv, int dst_stride_uv,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
int UYVYToNV12(const uint8* src_uyvy, int src_stride_uyvy,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_uv, int dst_stride_uv,
|
||||
int width, int height);
|
||||
|
||||
// Convert I420 to I400. (calls CopyPlane ignoring u/v).
|
||||
LIBYUV_API
|
||||
int I420ToI400(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
int width, int height);
|
||||
|
||||
// Alias
|
||||
#define J420ToJ400 I420ToI400
|
||||
#define I420ToI420Mirror I420Mirror
|
||||
|
||||
// I420 mirror.
|
||||
LIBYUV_API
|
||||
int I420Mirror(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Alias
|
||||
#define I400ToI400Mirror I400Mirror
|
||||
|
||||
// I400 mirror. A single plane is mirrored horizontally.
|
||||
// Pass negative height to achieve 180 degree rotation.
|
||||
LIBYUV_API
|
||||
int I400Mirror(const uint8* src_y, int src_stride_y,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
int width, int height);
|
||||
|
||||
// Alias
|
||||
#define ARGBToARGBMirror ARGBMirror
|
||||
|
||||
// ARGB mirror.
|
||||
LIBYUV_API
|
||||
int ARGBMirror(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert NV12 to RGB565.
|
||||
LIBYUV_API
|
||||
int NV12ToRGB565(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_uv, int src_stride_uv,
|
||||
uint8* dst_rgb565, int dst_stride_rgb565,
|
||||
int width, int height);
|
||||
|
||||
// I422ToARGB is in convert_argb.h
|
||||
// Convert I422 to BGRA.
|
||||
LIBYUV_API
|
||||
int I422ToBGRA(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_bgra, int dst_stride_bgra,
|
||||
int width, int height);
|
||||
|
||||
// Convert I422 to ABGR.
|
||||
LIBYUV_API
|
||||
int I422ToABGR(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_abgr, int dst_stride_abgr,
|
||||
int width, int height);
|
||||
|
||||
// Convert I422 to RGBA.
|
||||
LIBYUV_API
|
||||
int I422ToRGBA(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_rgba, int dst_stride_rgba,
|
||||
int width, int height);
|
||||
|
||||
// Alias
|
||||
#define RGB24ToRAW RAWToRGB24
|
||||
|
||||
LIBYUV_API
|
||||
int RAWToRGB24(const uint8* src_raw, int src_stride_raw,
|
||||
uint8* dst_rgb24, int dst_stride_rgb24,
|
||||
int width, int height);
|
||||
|
||||
// Draw a rectangle into I420.
|
||||
LIBYUV_API
|
||||
int I420Rect(uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int x, int y, int width, int height,
|
||||
int value_y, int value_u, int value_v);
|
||||
|
||||
// Draw a rectangle into ARGB.
|
||||
LIBYUV_API
|
||||
int ARGBRect(uint8* dst_argb, int dst_stride_argb,
|
||||
int x, int y, int width, int height, uint32 value);
|
||||
|
||||
// Convert ARGB to gray scale ARGB.
|
||||
LIBYUV_API
|
||||
int ARGBGrayTo(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Make a rectangle of ARGB gray scale.
|
||||
LIBYUV_API
|
||||
int ARGBGray(uint8* dst_argb, int dst_stride_argb,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
// Make a rectangle of ARGB Sepia tone.
|
||||
LIBYUV_API
|
||||
int ARGBSepia(uint8* dst_argb, int dst_stride_argb,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
// Apply a matrix rotation to each ARGB pixel.
|
||||
// matrix_argb is 4 signed ARGB values. -128 to 127 representing -2 to 2.
|
||||
// The first 4 coefficients apply to B, G, R, A and produce B of the output.
|
||||
// The next 4 coefficients apply to B, G, R, A and produce G of the output.
|
||||
// The next 4 coefficients apply to B, G, R, A and produce R of the output.
|
||||
// The last 4 coefficients apply to B, G, R, A and produce A of the output.
|
||||
LIBYUV_API
|
||||
int ARGBColorMatrix(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
const int8* matrix_argb,
|
||||
int width, int height);
|
||||
|
||||
// Deprecated. Use ARGBColorMatrix instead.
|
||||
// Apply a matrix rotation to each ARGB pixel.
|
||||
// matrix_argb is 3 signed ARGB values. -128 to 127 representing -1 to 1.
|
||||
// The first 4 coefficients apply to B, G, R, A and produce B of the output.
|
||||
// The next 4 coefficients apply to B, G, R, A and produce G of the output.
|
||||
// The last 4 coefficients apply to B, G, R, A and produce R of the output.
|
||||
LIBYUV_API
|
||||
int RGBColorMatrix(uint8* dst_argb, int dst_stride_argb,
|
||||
const int8* matrix_rgb,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
// Apply a color table each ARGB pixel.
|
||||
// Table contains 256 ARGB values.
|
||||
LIBYUV_API
|
||||
int ARGBColorTable(uint8* dst_argb, int dst_stride_argb,
|
||||
const uint8* table_argb,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
// Apply a color table each ARGB pixel but preserve destination alpha.
|
||||
// Table contains 256 ARGB values.
|
||||
LIBYUV_API
|
||||
int RGBColorTable(uint8* dst_argb, int dst_stride_argb,
|
||||
const uint8* table_argb,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
// Apply a luma/color table each ARGB pixel but preserve destination alpha.
|
||||
// Table contains 32768 values indexed by [Y][C] where 7 it 7 bit luma from
|
||||
// RGB (YJ style) and C is an 8 bit color component (R, G or B).
|
||||
LIBYUV_API
|
||||
int ARGBLumaColorTable(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
const uint8* luma_rgb_table,
|
||||
int width, int height);
|
||||
|
||||
// Apply a 3 term polynomial to ARGB values.
|
||||
// poly points to a 4x4 matrix. The first row is constants. The 2nd row is
|
||||
// coefficients for b, g, r and a. The 3rd row is coefficients for b squared,
|
||||
// g squared, r squared and a squared. The 4rd row is coefficients for b to
|
||||
// the 3, g to the 3, r to the 3 and a to the 3. The values are summed and
|
||||
// result clamped to 0 to 255.
|
||||
// A polynomial approximation can be dirived using software such as 'R'.
|
||||
|
||||
LIBYUV_API
|
||||
int ARGBPolynomial(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
const float* poly,
|
||||
int width, int height);
|
||||
|
||||
// Convert plane of 16 bit shorts to half floats.
|
||||
// Source values are multiplied by scale before storing as half float.
|
||||
LIBYUV_API
|
||||
int HalfFloatPlane(const uint16* src_y, int src_stride_y,
|
||||
uint16* dst_y, int dst_stride_y,
|
||||
float scale,
|
||||
int width, int height);
|
||||
|
||||
// Quantize a rectangle of ARGB. Alpha unaffected.
|
||||
// scale is a 16 bit fractional fixed point scaler between 0 and 65535.
|
||||
// interval_size should be a value between 1 and 255.
|
||||
// interval_offset should be a value between 0 and 255.
|
||||
LIBYUV_API
|
||||
int ARGBQuantize(uint8* dst_argb, int dst_stride_argb,
|
||||
int scale, int interval_size, int interval_offset,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
// Copy ARGB to ARGB.
|
||||
LIBYUV_API
|
||||
int ARGBCopy(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Copy Alpha channel of ARGB to alpha of ARGB.
|
||||
LIBYUV_API
|
||||
int ARGBCopyAlpha(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Extract the alpha channel from ARGB.
|
||||
LIBYUV_API
|
||||
int ARGBExtractAlpha(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_a, int dst_stride_a,
|
||||
int width, int height);
|
||||
|
||||
// Copy Y channel to Alpha of ARGB.
|
||||
LIBYUV_API
|
||||
int ARGBCopyYToAlpha(const uint8* src_y, int src_stride_y,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
typedef void (*ARGBBlendRow)(const uint8* src_argb0, const uint8* src_argb1,
|
||||
uint8* dst_argb, int width);
|
||||
|
||||
// Get function to Alpha Blend ARGB pixels and store to destination.
|
||||
LIBYUV_API
|
||||
ARGBBlendRow GetARGBBlend();
|
||||
|
||||
// Alpha Blend ARGB images and store to destination.
|
||||
// Source is pre-multiplied by alpha using ARGBAttenuate.
|
||||
// Alpha of destination is set to 255.
|
||||
LIBYUV_API
|
||||
int ARGBBlend(const uint8* src_argb0, int src_stride_argb0,
|
||||
const uint8* src_argb1, int src_stride_argb1,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Alpha Blend plane and store to destination.
|
||||
// Source is not pre-multiplied by alpha.
|
||||
LIBYUV_API
|
||||
int BlendPlane(const uint8* src_y0, int src_stride_y0,
|
||||
const uint8* src_y1, int src_stride_y1,
|
||||
const uint8* alpha, int alpha_stride,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
int width, int height);
|
||||
|
||||
// Alpha Blend YUV images and store to destination.
|
||||
// Source is not pre-multiplied by alpha.
|
||||
// Alpha is full width x height and subsampled to half size to apply to UV.
|
||||
LIBYUV_API
|
||||
int I420Blend(const uint8* src_y0, int src_stride_y0,
|
||||
const uint8* src_u0, int src_stride_u0,
|
||||
const uint8* src_v0, int src_stride_v0,
|
||||
const uint8* src_y1, int src_stride_y1,
|
||||
const uint8* src_u1, int src_stride_u1,
|
||||
const uint8* src_v1, int src_stride_v1,
|
||||
const uint8* alpha, int alpha_stride,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height);
|
||||
|
||||
// Multiply ARGB image by ARGB image. Shifted down by 8. Saturates to 255.
|
||||
LIBYUV_API
|
||||
int ARGBMultiply(const uint8* src_argb0, int src_stride_argb0,
|
||||
const uint8* src_argb1, int src_stride_argb1,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Add ARGB image with ARGB image. Saturates to 255.
|
||||
LIBYUV_API
|
||||
int ARGBAdd(const uint8* src_argb0, int src_stride_argb0,
|
||||
const uint8* src_argb1, int src_stride_argb1,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Subtract ARGB image (argb1) from ARGB image (argb0). Saturates to 0.
|
||||
LIBYUV_API
|
||||
int ARGBSubtract(const uint8* src_argb0, int src_stride_argb0,
|
||||
const uint8* src_argb1, int src_stride_argb1,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert I422 to YUY2.
|
||||
LIBYUV_API
|
||||
int I422ToYUY2(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_frame, int dst_stride_frame,
|
||||
int width, int height);
|
||||
|
||||
// Convert I422 to UYVY.
|
||||
LIBYUV_API
|
||||
int I422ToUYVY(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_frame, int dst_stride_frame,
|
||||
int width, int height);
|
||||
|
||||
// Convert unattentuated ARGB to preattenuated ARGB.
|
||||
LIBYUV_API
|
||||
int ARGBAttenuate(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Convert preattentuated ARGB to unattenuated ARGB.
|
||||
LIBYUV_API
|
||||
int ARGBUnattenuate(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Internal function - do not call directly.
|
||||
// Computes table of cumulative sum for image where the value is the sum
|
||||
// of all values above and to the left of the entry. Used by ARGBBlur.
|
||||
LIBYUV_API
|
||||
int ARGBComputeCumulativeSum(const uint8* src_argb, int src_stride_argb,
|
||||
int32* dst_cumsum, int dst_stride32_cumsum,
|
||||
int width, int height);
|
||||
|
||||
// Blur ARGB image.
|
||||
// dst_cumsum table of width * (height + 1) * 16 bytes aligned to
|
||||
// 16 byte boundary.
|
||||
// dst_stride32_cumsum is number of ints in a row (width * 4).
|
||||
// radius is number of pixels around the center. e.g. 1 = 3x3. 2=5x5.
|
||||
// Blur is optimized for radius of 5 (11x11) or less.
|
||||
LIBYUV_API
|
||||
int ARGBBlur(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int32* dst_cumsum, int dst_stride32_cumsum,
|
||||
int width, int height, int radius);
|
||||
|
||||
// Multiply ARGB image by ARGB value.
|
||||
LIBYUV_API
|
||||
int ARGBShade(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height, uint32 value);
|
||||
|
||||
// Interpolate between two images using specified amount of interpolation
|
||||
// (0 to 255) and store to destination.
|
||||
// 'interpolation' is specified as 8 bit fraction where 0 means 100% src0
|
||||
// and 255 means 1% src0 and 99% src1.
|
||||
LIBYUV_API
|
||||
int InterpolatePlane(const uint8* src0, int src_stride0,
|
||||
const uint8* src1, int src_stride1,
|
||||
uint8* dst, int dst_stride,
|
||||
int width, int height, int interpolation);
|
||||
|
||||
// Interpolate between two ARGB images using specified amount of interpolation
|
||||
// Internally calls InterpolatePlane with width * 4 (bpp).
|
||||
LIBYUV_API
|
||||
int ARGBInterpolate(const uint8* src_argb0, int src_stride_argb0,
|
||||
const uint8* src_argb1, int src_stride_argb1,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height, int interpolation);
|
||||
|
||||
// Interpolate between two YUV images using specified amount of interpolation
|
||||
// Internally calls InterpolatePlane on each plane where the U and V planes
|
||||
// are half width and half height.
|
||||
LIBYUV_API
|
||||
int I420Interpolate(const uint8* src0_y, int src0_stride_y,
|
||||
const uint8* src0_u, int src0_stride_u,
|
||||
const uint8* src0_v, int src0_stride_v,
|
||||
const uint8* src1_y, int src1_stride_y,
|
||||
const uint8* src1_u, int src1_stride_u,
|
||||
const uint8* src1_v, int src1_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height, int interpolation);
|
||||
|
||||
#if defined(__pnacl__) || defined(__CLR_VER) || \
|
||||
(defined(__i386__) && !defined(__SSE2__))
|
||||
#define LIBYUV_DISABLE_X86
|
||||
#endif
|
||||
// MemorySanitizer does not support assembly code yet. http://crbug.com/344505
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#define LIBYUV_DISABLE_X86
|
||||
#endif
|
||||
#endif
|
||||
// The following are available on all x86 platforms:
|
||||
#if !defined(LIBYUV_DISABLE_X86) && \
|
||||
(defined(_M_IX86) || defined(__x86_64__) || defined(__i386__))
|
||||
#define HAS_ARGBAFFINEROW_SSE2
|
||||
#endif
|
||||
|
||||
// Row function for copying pixels from a source with a slope to a row
|
||||
// of destination. Useful for scaling, rotation, mirror, texture mapping.
|
||||
LIBYUV_API
|
||||
void ARGBAffineRow_C(const uint8* src_argb, int src_argb_stride,
|
||||
uint8* dst_argb, const float* uv_dudv, int width);
|
||||
LIBYUV_API
|
||||
void ARGBAffineRow_SSE2(const uint8* src_argb, int src_argb_stride,
|
||||
uint8* dst_argb, const float* uv_dudv, int width);
|
||||
|
||||
// Shuffle ARGB channel order. e.g. BGRA to ARGB.
|
||||
// shuffler is 16 bytes and must be aligned.
|
||||
LIBYUV_API
|
||||
int ARGBShuffle(const uint8* src_bgra, int src_stride_bgra,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
const uint8* shuffler, int width, int height);
|
||||
|
||||
// Sobel ARGB effect with planar output.
|
||||
LIBYUV_API
|
||||
int ARGBSobelToPlane(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
int width, int height);
|
||||
|
||||
// Sobel ARGB effect.
|
||||
LIBYUV_API
|
||||
int ARGBSobel(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
// Sobel ARGB effect w/ Sobel X, Sobel, Sobel Y in ARGB.
|
||||
LIBYUV_API
|
||||
int ARGBSobelXY(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int width, int height);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace libyuv
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_PLANAR_FUNCTIONS_H_
|
||||
117
third_party/libyuv/include/libyuv/rotate.h
vendored
117
third_party/libyuv/include/libyuv/rotate.h
vendored
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_ROTATE_H_
|
||||
#define INCLUDE_LIBYUV_ROTATE_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Supported rotation.
|
||||
typedef enum RotationMode {
|
||||
kRotate0 = 0, // No rotation.
|
||||
kRotate90 = 90, // Rotate 90 degrees clockwise.
|
||||
kRotate180 = 180, // Rotate 180 degrees.
|
||||
kRotate270 = 270, // Rotate 270 degrees clockwise.
|
||||
|
||||
// Deprecated.
|
||||
kRotateNone = 0,
|
||||
kRotateClockwise = 90,
|
||||
kRotateCounterClockwise = 270,
|
||||
} RotationModeEnum;
|
||||
|
||||
// Rotate I420 frame.
|
||||
LIBYUV_API
|
||||
int I420Rotate(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int src_width, int src_height, enum RotationMode mode);
|
||||
|
||||
// Rotate NV12 input and store in I420.
|
||||
LIBYUV_API
|
||||
int NV12ToI420Rotate(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_uv, int src_stride_uv,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int src_width, int src_height, enum RotationMode mode);
|
||||
|
||||
// Rotate a plane by 0, 90, 180, or 270.
|
||||
LIBYUV_API
|
||||
int RotatePlane(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride,
|
||||
int src_width, int src_height, enum RotationMode mode);
|
||||
|
||||
// Rotate planes by 90, 180, 270. Deprecated.
|
||||
LIBYUV_API
|
||||
void RotatePlane90(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
void RotatePlane180(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
void RotatePlane270(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
void RotateUV90(const uint8* src, int src_stride,
|
||||
uint8* dst_a, int dst_stride_a,
|
||||
uint8* dst_b, int dst_stride_b,
|
||||
int width, int height);
|
||||
|
||||
// Rotations for when U and V are interleaved.
|
||||
// These functions take one input pointer and
|
||||
// split the data into two buffers while
|
||||
// rotating them. Deprecated.
|
||||
LIBYUV_API
|
||||
void RotateUV180(const uint8* src, int src_stride,
|
||||
uint8* dst_a, int dst_stride_a,
|
||||
uint8* dst_b, int dst_stride_b,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
void RotateUV270(const uint8* src, int src_stride,
|
||||
uint8* dst_a, int dst_stride_a,
|
||||
uint8* dst_b, int dst_stride_b,
|
||||
int width, int height);
|
||||
|
||||
// The 90 and 270 functions are based on transposes.
|
||||
// Doing a transpose with reversing the read/write
|
||||
// order will result in a rotation by +- 90 degrees.
|
||||
// Deprecated.
|
||||
LIBYUV_API
|
||||
void TransposePlane(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride,
|
||||
int width, int height);
|
||||
|
||||
LIBYUV_API
|
||||
void TransposeUV(const uint8* src, int src_stride,
|
||||
uint8* dst_a, int dst_stride_a,
|
||||
uint8* dst_b, int dst_stride_b,
|
||||
int width, int height);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace libyuv
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_ROTATE_H_
|
||||
33
third_party/libyuv/include/libyuv/rotate_argb.h
vendored
33
third_party/libyuv/include/libyuv/rotate_argb.h
vendored
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_ROTATE_ARGB_H_
|
||||
#define INCLUDE_LIBYUV_ROTATE_ARGB_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
#include "libyuv/rotate.h" // For RotationMode.
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Rotate ARGB frame
|
||||
LIBYUV_API
|
||||
int ARGBRotate(const uint8* src_argb, int src_stride_argb,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int src_width, int src_height, enum RotationMode mode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace libyuv
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_ROTATE_ARGB_H_
|
||||
121
third_party/libyuv/include/libyuv/rotate_row.h
vendored
121
third_party/libyuv/include/libyuv/rotate_row.h
vendored
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_ROTATE_ROW_H_
|
||||
#define INCLUDE_LIBYUV_ROTATE_ROW_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__pnacl__) || defined(__CLR_VER) || \
|
||||
(defined(__i386__) && !defined(__SSE2__))
|
||||
#define LIBYUV_DISABLE_X86
|
||||
#endif
|
||||
// MemorySanitizer does not support assembly code yet. http://crbug.com/344505
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#define LIBYUV_DISABLE_X86
|
||||
#endif
|
||||
#endif
|
||||
// The following are available for Visual C and clangcl 32 bit:
|
||||
#if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86)
|
||||
#define HAS_TRANSPOSEWX8_SSSE3
|
||||
#define HAS_TRANSPOSEUVWX8_SSE2
|
||||
#endif
|
||||
|
||||
// The following are available for GCC 32 or 64 bit but not NaCL for 64 bit:
|
||||
#if !defined(LIBYUV_DISABLE_X86) && \
|
||||
(defined(__i386__) || (defined(__x86_64__) && !defined(__native_client__)))
|
||||
#define HAS_TRANSPOSEWX8_SSSE3
|
||||
#endif
|
||||
|
||||
// The following are available for 64 bit GCC but not NaCL:
|
||||
#if !defined(LIBYUV_DISABLE_X86) && !defined(__native_client__) && \
|
||||
defined(__x86_64__)
|
||||
#define HAS_TRANSPOSEWX8_FAST_SSSE3
|
||||
#define HAS_TRANSPOSEUVWX8_SSE2
|
||||
#endif
|
||||
|
||||
#if !defined(LIBYUV_DISABLE_NEON) && !defined(__native_client__) && \
|
||||
(defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__))
|
||||
#define HAS_TRANSPOSEWX8_NEON
|
||||
#define HAS_TRANSPOSEUVWX8_NEON
|
||||
#endif
|
||||
|
||||
#if !defined(LIBYUV_DISABLE_MIPS) && !defined(__native_client__) && \
|
||||
defined(__mips__) && \
|
||||
defined(__mips_dsp) && (__mips_dsp_rev >= 2)
|
||||
#define HAS_TRANSPOSEWX8_DSPR2
|
||||
#define HAS_TRANSPOSEUVWX8_DSPR2
|
||||
#endif // defined(__mips__)
|
||||
|
||||
void TransposeWxH_C(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride, int width, int height);
|
||||
|
||||
void TransposeWx8_C(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride, int width);
|
||||
void TransposeWx8_NEON(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride, int width);
|
||||
void TransposeWx8_SSSE3(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride, int width);
|
||||
void TransposeWx8_Fast_SSSE3(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride, int width);
|
||||
void TransposeWx8_DSPR2(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride, int width);
|
||||
void TransposeWx8_Fast_DSPR2(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride, int width);
|
||||
|
||||
void TransposeWx8_Any_NEON(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride, int width);
|
||||
void TransposeWx8_Any_SSSE3(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride, int width);
|
||||
void TransposeWx8_Fast_Any_SSSE3(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride, int width);
|
||||
void TransposeWx8_Any_DSPR2(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride, int width);
|
||||
|
||||
void TransposeUVWxH_C(const uint8* src, int src_stride,
|
||||
uint8* dst_a, int dst_stride_a,
|
||||
uint8* dst_b, int dst_stride_b,
|
||||
int width, int height);
|
||||
|
||||
void TransposeUVWx8_C(const uint8* src, int src_stride,
|
||||
uint8* dst_a, int dst_stride_a,
|
||||
uint8* dst_b, int dst_stride_b, int width);
|
||||
void TransposeUVWx8_SSE2(const uint8* src, int src_stride,
|
||||
uint8* dst_a, int dst_stride_a,
|
||||
uint8* dst_b, int dst_stride_b, int width);
|
||||
void TransposeUVWx8_NEON(const uint8* src, int src_stride,
|
||||
uint8* dst_a, int dst_stride_a,
|
||||
uint8* dst_b, int dst_stride_b, int width);
|
||||
void TransposeUVWx8_DSPR2(const uint8* src, int src_stride,
|
||||
uint8* dst_a, int dst_stride_a,
|
||||
uint8* dst_b, int dst_stride_b, int width);
|
||||
|
||||
void TransposeUVWx8_Any_SSE2(const uint8* src, int src_stride,
|
||||
uint8* dst_a, int dst_stride_a,
|
||||
uint8* dst_b, int dst_stride_b, int width);
|
||||
void TransposeUVWx8_Any_NEON(const uint8* src, int src_stride,
|
||||
uint8* dst_a, int dst_stride_a,
|
||||
uint8* dst_b, int dst_stride_b, int width);
|
||||
void TransposeUVWx8_Any_DSPR2(const uint8* src, int src_stride,
|
||||
uint8* dst_a, int dst_stride_a,
|
||||
uint8* dst_b, int dst_stride_b, int width);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace libyuv
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_ROTATE_ROW_H_
|
||||
1963
third_party/libyuv/include/libyuv/row.h
vendored
1963
third_party/libyuv/include/libyuv/row.h
vendored
File diff suppressed because it is too large
Load Diff
103
third_party/libyuv/include/libyuv/scale.h
vendored
103
third_party/libyuv/include/libyuv/scale.h
vendored
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_SCALE_H_
|
||||
#define INCLUDE_LIBYUV_SCALE_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Supported filtering.
|
||||
typedef enum FilterMode {
|
||||
kFilterNone = 0, // Point sample; Fastest.
|
||||
kFilterLinear = 1, // Filter horizontally only.
|
||||
kFilterBilinear = 2, // Faster than box, but lower quality scaling down.
|
||||
kFilterBox = 3 // Highest quality.
|
||||
} FilterModeEnum;
|
||||
|
||||
// Scale a YUV plane.
|
||||
LIBYUV_API
|
||||
void ScalePlane(const uint8* src, int src_stride,
|
||||
int src_width, int src_height,
|
||||
uint8* dst, int dst_stride,
|
||||
int dst_width, int dst_height,
|
||||
enum FilterMode filtering);
|
||||
|
||||
LIBYUV_API
|
||||
void ScalePlane_16(const uint16* src, int src_stride,
|
||||
int src_width, int src_height,
|
||||
uint16* dst, int dst_stride,
|
||||
int dst_width, int dst_height,
|
||||
enum FilterMode filtering);
|
||||
|
||||
// Scales a YUV 4:2:0 image from the src width and height to the
|
||||
// dst width and height.
|
||||
// If filtering is kFilterNone, a simple nearest-neighbor algorithm is
|
||||
// used. This produces basic (blocky) quality at the fastest speed.
|
||||
// If filtering is kFilterBilinear, interpolation is used to produce a better
|
||||
// quality image, at the expense of speed.
|
||||
// If filtering is kFilterBox, averaging is used to produce ever better
|
||||
// quality image, at further expense of speed.
|
||||
// Returns 0 if successful.
|
||||
|
||||
LIBYUV_API
|
||||
int I420Scale(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
int src_width, int src_height,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int dst_width, int dst_height,
|
||||
enum FilterMode filtering);
|
||||
|
||||
LIBYUV_API
|
||||
int I420Scale_16(const uint16* src_y, int src_stride_y,
|
||||
const uint16* src_u, int src_stride_u,
|
||||
const uint16* src_v, int src_stride_v,
|
||||
int src_width, int src_height,
|
||||
uint16* dst_y, int dst_stride_y,
|
||||
uint16* dst_u, int dst_stride_u,
|
||||
uint16* dst_v, int dst_stride_v,
|
||||
int dst_width, int dst_height,
|
||||
enum FilterMode filtering);
|
||||
|
||||
#ifdef __cplusplus
|
||||
// Legacy API. Deprecated.
|
||||
LIBYUV_API
|
||||
int Scale(const uint8* src_y, const uint8* src_u, const uint8* src_v,
|
||||
int src_stride_y, int src_stride_u, int src_stride_v,
|
||||
int src_width, int src_height,
|
||||
uint8* dst_y, uint8* dst_u, uint8* dst_v,
|
||||
int dst_stride_y, int dst_stride_u, int dst_stride_v,
|
||||
int dst_width, int dst_height,
|
||||
LIBYUV_BOOL interpolate);
|
||||
|
||||
// Legacy API. Deprecated.
|
||||
LIBYUV_API
|
||||
int ScaleOffset(const uint8* src_i420, int src_width, int src_height,
|
||||
uint8* dst_i420, int dst_width, int dst_height, int dst_yoffset,
|
||||
LIBYUV_BOOL interpolate);
|
||||
|
||||
// For testing, allow disabling of specialized scalers.
|
||||
LIBYUV_API
|
||||
void SetUseReferenceImpl(LIBYUV_BOOL use);
|
||||
#endif // __cplusplus
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace libyuv
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_SCALE_H_
|
||||
56
third_party/libyuv/include/libyuv/scale_argb.h
vendored
56
third_party/libyuv/include/libyuv/scale_argb.h
vendored
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_SCALE_ARGB_H_
|
||||
#define INCLUDE_LIBYUV_SCALE_ARGB_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
#include "libyuv/scale.h" // For FilterMode
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
LIBYUV_API
|
||||
int ARGBScale(const uint8* src_argb, int src_stride_argb,
|
||||
int src_width, int src_height,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int dst_width, int dst_height,
|
||||
enum FilterMode filtering);
|
||||
|
||||
// Clipped scale takes destination rectangle coordinates for clip values.
|
||||
LIBYUV_API
|
||||
int ARGBScaleClip(const uint8* src_argb, int src_stride_argb,
|
||||
int src_width, int src_height,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int dst_width, int dst_height,
|
||||
int clip_x, int clip_y, int clip_width, int clip_height,
|
||||
enum FilterMode filtering);
|
||||
|
||||
// Scale with YUV conversion to ARGB and clipping.
|
||||
LIBYUV_API
|
||||
int YUVToARGBScaleClip(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint32 src_fourcc,
|
||||
int src_width, int src_height,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
uint32 dst_fourcc,
|
||||
int dst_width, int dst_height,
|
||||
int clip_x, int clip_y, int clip_width, int clip_height,
|
||||
enum FilterMode filtering);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace libyuv
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_SCALE_ARGB_H_
|
||||
503
third_party/libyuv/include/libyuv/scale_row.h
vendored
503
third_party/libyuv/include/libyuv/scale_row.h
vendored
@@ -1,503 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_SCALE_ROW_H_
|
||||
#define INCLUDE_LIBYUV_SCALE_ROW_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
#include "libyuv/scale.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__pnacl__) || defined(__CLR_VER) || \
|
||||
(defined(__i386__) && !defined(__SSE2__))
|
||||
#define LIBYUV_DISABLE_X86
|
||||
#endif
|
||||
// MemorySanitizer does not support assembly code yet. http://crbug.com/344505
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#define LIBYUV_DISABLE_X86
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// GCC >= 4.7.0 required for AVX2.
|
||||
#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
|
||||
#if (__GNUC__ > 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 7))
|
||||
#define GCC_HAS_AVX2 1
|
||||
#endif // GNUC >= 4.7
|
||||
#endif // __GNUC__
|
||||
|
||||
// clang >= 3.4.0 required for AVX2.
|
||||
#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__))
|
||||
#if (__clang_major__ > 3) || (__clang_major__ == 3 && (__clang_minor__ >= 4))
|
||||
#define CLANG_HAS_AVX2 1
|
||||
#endif // clang >= 3.4
|
||||
#endif // __clang__
|
||||
|
||||
// Visual C 2012 required for AVX2.
|
||||
#if defined(_M_IX86) && !defined(__clang__) && \
|
||||
defined(_MSC_VER) && _MSC_VER >= 1700
|
||||
#define VISUALC_HAS_AVX2 1
|
||||
#endif // VisualStudio >= 2012
|
||||
|
||||
// The following are available on all x86 platforms:
|
||||
#if !defined(LIBYUV_DISABLE_X86) && \
|
||||
(defined(_M_IX86) || defined(__x86_64__) || defined(__i386__))
|
||||
#define HAS_FIXEDDIV1_X86
|
||||
#define HAS_FIXEDDIV_X86
|
||||
#define HAS_SCALEARGBCOLS_SSE2
|
||||
#define HAS_SCALEARGBCOLSUP2_SSE2
|
||||
#define HAS_SCALEARGBFILTERCOLS_SSSE3
|
||||
#define HAS_SCALEARGBROWDOWN2_SSE2
|
||||
#define HAS_SCALEARGBROWDOWNEVEN_SSE2
|
||||
#define HAS_SCALECOLSUP2_SSE2
|
||||
#define HAS_SCALEFILTERCOLS_SSSE3
|
||||
#define HAS_SCALEROWDOWN2_SSSE3
|
||||
#define HAS_SCALEROWDOWN34_SSSE3
|
||||
#define HAS_SCALEROWDOWN38_SSSE3
|
||||
#define HAS_SCALEROWDOWN4_SSSE3
|
||||
#define HAS_SCALEADDROW_SSE2
|
||||
#endif
|
||||
|
||||
// The following are available on all x86 platforms, but
|
||||
// require VS2012, clang 3.4 or gcc 4.7.
|
||||
// The code supports NaCL but requires a new compiler and validator.
|
||||
#if !defined(LIBYUV_DISABLE_X86) && (defined(VISUALC_HAS_AVX2) || \
|
||||
defined(CLANG_HAS_AVX2) || defined(GCC_HAS_AVX2))
|
||||
#define HAS_SCALEADDROW_AVX2
|
||||
#define HAS_SCALEROWDOWN2_AVX2
|
||||
#define HAS_SCALEROWDOWN4_AVX2
|
||||
#endif
|
||||
|
||||
// The following are available on Neon platforms:
|
||||
#if !defined(LIBYUV_DISABLE_NEON) && !defined(__native_client__) && \
|
||||
(defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__))
|
||||
#define HAS_SCALEARGBCOLS_NEON
|
||||
#define HAS_SCALEARGBROWDOWN2_NEON
|
||||
#define HAS_SCALEARGBROWDOWNEVEN_NEON
|
||||
#define HAS_SCALEFILTERCOLS_NEON
|
||||
#define HAS_SCALEROWDOWN2_NEON
|
||||
#define HAS_SCALEROWDOWN34_NEON
|
||||
#define HAS_SCALEROWDOWN38_NEON
|
||||
#define HAS_SCALEROWDOWN4_NEON
|
||||
#define HAS_SCALEARGBFILTERCOLS_NEON
|
||||
#endif
|
||||
|
||||
// The following are available on Mips platforms:
|
||||
#if !defined(LIBYUV_DISABLE_MIPS) && !defined(__native_client__) && \
|
||||
defined(__mips__) && defined(__mips_dsp) && (__mips_dsp_rev >= 2)
|
||||
#define HAS_SCALEROWDOWN2_DSPR2
|
||||
#define HAS_SCALEROWDOWN4_DSPR2
|
||||
#define HAS_SCALEROWDOWN34_DSPR2
|
||||
#define HAS_SCALEROWDOWN38_DSPR2
|
||||
#endif
|
||||
|
||||
// Scale ARGB vertically with bilinear interpolation.
|
||||
void ScalePlaneVertical(int src_height,
|
||||
int dst_width, int dst_height,
|
||||
int src_stride, int dst_stride,
|
||||
const uint8* src_argb, uint8* dst_argb,
|
||||
int x, int y, int dy,
|
||||
int bpp, enum FilterMode filtering);
|
||||
|
||||
void ScalePlaneVertical_16(int src_height,
|
||||
int dst_width, int dst_height,
|
||||
int src_stride, int dst_stride,
|
||||
const uint16* src_argb, uint16* dst_argb,
|
||||
int x, int y, int dy,
|
||||
int wpp, enum FilterMode filtering);
|
||||
|
||||
// Simplify the filtering based on scale factors.
|
||||
enum FilterMode ScaleFilterReduce(int src_width, int src_height,
|
||||
int dst_width, int dst_height,
|
||||
enum FilterMode filtering);
|
||||
|
||||
// Divide num by div and return as 16.16 fixed point result.
|
||||
int FixedDiv_C(int num, int div);
|
||||
int FixedDiv_X86(int num, int div);
|
||||
// Divide num - 1 by div - 1 and return as 16.16 fixed point result.
|
||||
int FixedDiv1_C(int num, int div);
|
||||
int FixedDiv1_X86(int num, int div);
|
||||
#ifdef HAS_FIXEDDIV_X86
|
||||
#define FixedDiv FixedDiv_X86
|
||||
#define FixedDiv1 FixedDiv1_X86
|
||||
#else
|
||||
#define FixedDiv FixedDiv_C
|
||||
#define FixedDiv1 FixedDiv1_C
|
||||
#endif
|
||||
|
||||
// Compute slope values for stepping.
|
||||
void ScaleSlope(int src_width, int src_height,
|
||||
int dst_width, int dst_height,
|
||||
enum FilterMode filtering,
|
||||
int* x, int* y, int* dx, int* dy);
|
||||
|
||||
void ScaleRowDown2_C(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown2_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
|
||||
uint16* dst, int dst_width);
|
||||
void ScaleRowDown2Linear_C(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown2Linear_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
|
||||
uint16* dst, int dst_width);
|
||||
void ScaleRowDown2Box_C(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown2Box_Odd_C(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown2Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
|
||||
uint16* dst, int dst_width);
|
||||
void ScaleRowDown4_C(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown4_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
|
||||
uint16* dst, int dst_width);
|
||||
void ScaleRowDown4Box_C(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown4Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
|
||||
uint16* dst, int dst_width);
|
||||
void ScaleRowDown34_C(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown34_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
|
||||
uint16* dst, int dst_width);
|
||||
void ScaleRowDown34_0_Box_C(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* d, int dst_width);
|
||||
void ScaleRowDown34_0_Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
|
||||
uint16* d, int dst_width);
|
||||
void ScaleRowDown34_1_Box_C(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* d, int dst_width);
|
||||
void ScaleRowDown34_1_Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
|
||||
uint16* d, int dst_width);
|
||||
void ScaleCols_C(uint8* dst_ptr, const uint8* src_ptr,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleCols_16_C(uint16* dst_ptr, const uint16* src_ptr,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleColsUp2_C(uint8* dst_ptr, const uint8* src_ptr,
|
||||
int dst_width, int, int);
|
||||
void ScaleColsUp2_16_C(uint16* dst_ptr, const uint16* src_ptr,
|
||||
int dst_width, int, int);
|
||||
void ScaleFilterCols_C(uint8* dst_ptr, const uint8* src_ptr,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleFilterCols_16_C(uint16* dst_ptr, const uint16* src_ptr,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleFilterCols64_C(uint8* dst_ptr, const uint8* src_ptr,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleFilterCols64_16_C(uint16* dst_ptr, const uint16* src_ptr,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleRowDown38_C(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown38_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
|
||||
uint16* dst, int dst_width);
|
||||
void ScaleRowDown38_3_Box_C(const uint8* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown38_3_Box_16_C(const uint16* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint16* dst_ptr, int dst_width);
|
||||
void ScaleRowDown38_2_Box_C(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown38_2_Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
|
||||
uint16* dst_ptr, int dst_width);
|
||||
void ScaleAddRow_C(const uint8* src_ptr, uint16* dst_ptr, int src_width);
|
||||
void ScaleAddRow_16_C(const uint16* src_ptr, uint32* dst_ptr, int src_width);
|
||||
void ScaleARGBRowDown2_C(const uint8* src_argb,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDown2Linear_C(const uint8* src_argb,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDown2Box_C(const uint8* src_argb, ptrdiff_t src_stride,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDownEven_C(const uint8* src_argb, ptrdiff_t src_stride,
|
||||
int src_stepx,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDownEvenBox_C(const uint8* src_argb,
|
||||
ptrdiff_t src_stride,
|
||||
int src_stepx,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBCols_C(uint8* dst_argb, const uint8* src_argb,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleARGBCols64_C(uint8* dst_argb, const uint8* src_argb,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleARGBColsUp2_C(uint8* dst_argb, const uint8* src_argb,
|
||||
int dst_width, int, int);
|
||||
void ScaleARGBFilterCols_C(uint8* dst_argb, const uint8* src_argb,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleARGBFilterCols64_C(uint8* dst_argb, const uint8* src_argb,
|
||||
int dst_width, int x, int dx);
|
||||
|
||||
// Specialized scalers for x86.
|
||||
void ScaleRowDown2_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown2Linear_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown2Box_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown2_AVX2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown2Linear_AVX2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown2Box_AVX2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown4_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown4Box_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown4_AVX2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown4Box_AVX2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
|
||||
void ScaleRowDown34_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown34_1_Box_SSSE3(const uint8* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown34_0_Box_SSSE3(const uint8* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown38_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown38_3_Box_SSSE3(const uint8* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown38_2_Box_SSSE3(const uint8* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown2_Any_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown2Linear_Any_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown2Box_Any_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown2Box_Odd_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown2_Any_AVX2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown2Linear_Any_AVX2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown2Box_Any_AVX2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown2Box_Odd_AVX2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown4_Any_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown4Box_Any_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown4_Any_AVX2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown4Box_Any_AVX2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
|
||||
void ScaleRowDown34_Any_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown34_1_Box_Any_SSSE3(const uint8* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown34_0_Box_Any_SSSE3(const uint8* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown38_Any_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown38_3_Box_Any_SSSE3(const uint8* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown38_2_Box_Any_SSSE3(const uint8* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
|
||||
void ScaleAddRow_SSE2(const uint8* src_ptr, uint16* dst_ptr, int src_width);
|
||||
void ScaleAddRow_AVX2(const uint8* src_ptr, uint16* dst_ptr, int src_width);
|
||||
void ScaleAddRow_Any_SSE2(const uint8* src_ptr, uint16* dst_ptr, int src_width);
|
||||
void ScaleAddRow_Any_AVX2(const uint8* src_ptr, uint16* dst_ptr, int src_width);
|
||||
|
||||
void ScaleFilterCols_SSSE3(uint8* dst_ptr, const uint8* src_ptr,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleColsUp2_SSE2(uint8* dst_ptr, const uint8* src_ptr,
|
||||
int dst_width, int x, int dx);
|
||||
|
||||
|
||||
// ARGB Column functions
|
||||
void ScaleARGBCols_SSE2(uint8* dst_argb, const uint8* src_argb,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleARGBFilterCols_SSSE3(uint8* dst_argb, const uint8* src_argb,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleARGBColsUp2_SSE2(uint8* dst_argb, const uint8* src_argb,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleARGBFilterCols_NEON(uint8* dst_argb, const uint8* src_argb,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleARGBCols_NEON(uint8* dst_argb, const uint8* src_argb,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleARGBFilterCols_Any_NEON(uint8* dst_argb, const uint8* src_argb,
|
||||
int dst_width, int x, int dx);
|
||||
void ScaleARGBCols_Any_NEON(uint8* dst_argb, const uint8* src_argb,
|
||||
int dst_width, int x, int dx);
|
||||
|
||||
// ARGB Row functions
|
||||
void ScaleARGBRowDown2_SSE2(const uint8* src_argb, ptrdiff_t src_stride,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDown2Linear_SSE2(const uint8* src_argb, ptrdiff_t src_stride,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDown2Box_SSE2(const uint8* src_argb, ptrdiff_t src_stride,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleARGBRowDown2Linear_NEON(const uint8* src_argb, ptrdiff_t src_stride,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleARGBRowDown2_Any_SSE2(const uint8* src_argb, ptrdiff_t src_stride,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDown2Linear_Any_SSE2(const uint8* src_argb,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDown2Box_Any_SSE2(const uint8* src_argb, ptrdiff_t src_stride,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDown2_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleARGBRowDown2Linear_Any_NEON(const uint8* src_argb,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDown2Box_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
|
||||
void ScaleARGBRowDownEven_SSE2(const uint8* src_argb, ptrdiff_t src_stride,
|
||||
int src_stepx, uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDownEvenBox_SSE2(const uint8* src_argb, ptrdiff_t src_stride,
|
||||
int src_stepx,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDownEven_NEON(const uint8* src_argb, ptrdiff_t src_stride,
|
||||
int src_stepx,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDownEvenBox_NEON(const uint8* src_argb, ptrdiff_t src_stride,
|
||||
int src_stepx,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDownEven_Any_SSE2(const uint8* src_argb, ptrdiff_t src_stride,
|
||||
int src_stepx,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDownEvenBox_Any_SSE2(const uint8* src_argb,
|
||||
ptrdiff_t src_stride,
|
||||
int src_stepx,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDownEven_Any_NEON(const uint8* src_argb, ptrdiff_t src_stride,
|
||||
int src_stepx,
|
||||
uint8* dst_argb, int dst_width);
|
||||
void ScaleARGBRowDownEvenBox_Any_NEON(const uint8* src_argb,
|
||||
ptrdiff_t src_stride,
|
||||
int src_stepx,
|
||||
uint8* dst_argb, int dst_width);
|
||||
|
||||
// ScaleRowDown2Box also used by planar functions
|
||||
// NEON downscalers with interpolation.
|
||||
|
||||
// Note - not static due to reuse in convert for 444 to 420.
|
||||
void ScaleRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown2Linear_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
|
||||
void ScaleRowDown4_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown4Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
|
||||
// Down scale from 4 to 3 pixels. Use the neon multilane read/write
|
||||
// to load up the every 4th pixel into a 4 different registers.
|
||||
// Point samples 32 pixels to 24 pixels.
|
||||
void ScaleRowDown34_NEON(const uint8* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown34_0_Box_NEON(const uint8* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown34_1_Box_NEON(const uint8* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
|
||||
// 32 -> 12
|
||||
void ScaleRowDown38_NEON(const uint8* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
// 32x3 -> 12x1
|
||||
void ScaleRowDown38_3_Box_NEON(const uint8* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
// 32x2 -> 12x1
|
||||
void ScaleRowDown38_2_Box_NEON(const uint8* src_ptr,
|
||||
ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
|
||||
void ScaleRowDown2_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown2Linear_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown2Box_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown2Box_Odd_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown4_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown4Box_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown34_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown34_0_Box_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown34_1_Box_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
// 32 -> 12
|
||||
void ScaleRowDown38_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
// 32x3 -> 12x1
|
||||
void ScaleRowDown38_3_Box_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
// 32x2 -> 12x1
|
||||
void ScaleRowDown38_2_Box_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
|
||||
void ScaleAddRow_NEON(const uint8* src_ptr, uint16* dst_ptr, int src_width);
|
||||
void ScaleAddRow_Any_NEON(const uint8* src_ptr, uint16* dst_ptr, int src_width);
|
||||
|
||||
void ScaleFilterCols_NEON(uint8* dst_ptr, const uint8* src_ptr,
|
||||
int dst_width, int x, int dx);
|
||||
|
||||
void ScaleFilterCols_Any_NEON(uint8* dst_ptr, const uint8* src_ptr,
|
||||
int dst_width, int x, int dx);
|
||||
|
||||
void ScaleRowDown2_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown2Box_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown4_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown4Box_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown34_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown34_0_Box_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* d, int dst_width);
|
||||
void ScaleRowDown34_1_Box_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* d, int dst_width);
|
||||
void ScaleRowDown38_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst, int dst_width);
|
||||
void ScaleRowDown38_2_Box_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
void ScaleRowDown38_3_Box_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride,
|
||||
uint8* dst_ptr, int dst_width);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace libyuv
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_SCALE_ROW_H_
|
||||
16
third_party/libyuv/include/libyuv/version.h
vendored
16
third_party/libyuv/include/libyuv/version.h
vendored
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_VERSION_H_
|
||||
#define INCLUDE_LIBYUV_VERSION_H_
|
||||
|
||||
#define LIBYUV_VERSION 1622
|
||||
|
||||
#endif // INCLUDE_LIBYUV_VERSION_H_
|
||||
184
third_party/libyuv/include/libyuv/video_common.h
vendored
184
third_party/libyuv/include/libyuv/video_common.h
vendored
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Common definitions for video, including fourcc and VideoFormat.
|
||||
|
||||
#ifndef INCLUDE_LIBYUV_VIDEO_COMMON_H_
|
||||
#define INCLUDE_LIBYUV_VIDEO_COMMON_H_
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Definition of FourCC codes
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Convert four characters to a FourCC code.
|
||||
// Needs to be a macro otherwise the OS X compiler complains when the kFormat*
|
||||
// constants are used in a switch.
|
||||
#ifdef __cplusplus
|
||||
#define FOURCC(a, b, c, d) ( \
|
||||
(static_cast<uint32>(a)) | (static_cast<uint32>(b) << 8) | \
|
||||
(static_cast<uint32>(c) << 16) | (static_cast<uint32>(d) << 24))
|
||||
#else
|
||||
#define FOURCC(a, b, c, d) ( \
|
||||
((uint32)(a)) | ((uint32)(b) << 8) | /* NOLINT */ \
|
||||
((uint32)(c) << 16) | ((uint32)(d) << 24)) /* NOLINT */
|
||||
#endif
|
||||
|
||||
// Some pages discussing FourCC codes:
|
||||
// http://www.fourcc.org/yuv.php
|
||||
// http://v4l2spec.bytesex.org/spec/book1.htm
|
||||
// http://developer.apple.com/quicktime/icefloe/dispatch020.html
|
||||
// http://msdn.microsoft.com/library/windows/desktop/dd206750.aspx#nv12
|
||||
// http://people.xiph.org/~xiphmont/containers/nut/nut4cc.txt
|
||||
|
||||
// FourCC codes grouped according to implementation efficiency.
|
||||
// Primary formats should convert in 1 efficient step.
|
||||
// Secondary formats are converted in 2 steps.
|
||||
// Auxilliary formats call primary converters.
|
||||
enum FourCC {
|
||||
// 9 Primary YUV formats: 5 planar, 2 biplanar, 2 packed.
|
||||
FOURCC_I420 = FOURCC('I', '4', '2', '0'),
|
||||
FOURCC_I422 = FOURCC('I', '4', '2', '2'),
|
||||
FOURCC_I444 = FOURCC('I', '4', '4', '4'),
|
||||
FOURCC_I411 = FOURCC('I', '4', '1', '1'),
|
||||
FOURCC_I400 = FOURCC('I', '4', '0', '0'),
|
||||
FOURCC_NV21 = FOURCC('N', 'V', '2', '1'),
|
||||
FOURCC_NV12 = FOURCC('N', 'V', '1', '2'),
|
||||
FOURCC_YUY2 = FOURCC('Y', 'U', 'Y', '2'),
|
||||
FOURCC_UYVY = FOURCC('U', 'Y', 'V', 'Y'),
|
||||
|
||||
// 2 Secondary YUV formats: row biplanar.
|
||||
FOURCC_M420 = FOURCC('M', '4', '2', '0'),
|
||||
FOURCC_Q420 = FOURCC('Q', '4', '2', '0'), // deprecated.
|
||||
|
||||
// 9 Primary RGB formats: 4 32 bpp, 2 24 bpp, 3 16 bpp.
|
||||
FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B'),
|
||||
FOURCC_BGRA = FOURCC('B', 'G', 'R', 'A'),
|
||||
FOURCC_ABGR = FOURCC('A', 'B', 'G', 'R'),
|
||||
FOURCC_24BG = FOURCC('2', '4', 'B', 'G'),
|
||||
FOURCC_RAW = FOURCC('r', 'a', 'w', ' '),
|
||||
FOURCC_RGBA = FOURCC('R', 'G', 'B', 'A'),
|
||||
FOURCC_RGBP = FOURCC('R', 'G', 'B', 'P'), // rgb565 LE.
|
||||
FOURCC_RGBO = FOURCC('R', 'G', 'B', 'O'), // argb1555 LE.
|
||||
FOURCC_R444 = FOURCC('R', '4', '4', '4'), // argb4444 LE.
|
||||
|
||||
// 4 Secondary RGB formats: 4 Bayer Patterns. deprecated.
|
||||
FOURCC_RGGB = FOURCC('R', 'G', 'G', 'B'),
|
||||
FOURCC_BGGR = FOURCC('B', 'G', 'G', 'R'),
|
||||
FOURCC_GRBG = FOURCC('G', 'R', 'B', 'G'),
|
||||
FOURCC_GBRG = FOURCC('G', 'B', 'R', 'G'),
|
||||
|
||||
// 1 Primary Compressed YUV format.
|
||||
FOURCC_MJPG = FOURCC('M', 'J', 'P', 'G'),
|
||||
|
||||
// 5 Auxiliary YUV variations: 3 with U and V planes are swapped, 1 Alias.
|
||||
FOURCC_YV12 = FOURCC('Y', 'V', '1', '2'),
|
||||
FOURCC_YV16 = FOURCC('Y', 'V', '1', '6'),
|
||||
FOURCC_YV24 = FOURCC('Y', 'V', '2', '4'),
|
||||
FOURCC_YU12 = FOURCC('Y', 'U', '1', '2'), // Linux version of I420.
|
||||
FOURCC_J420 = FOURCC('J', '4', '2', '0'),
|
||||
FOURCC_J400 = FOURCC('J', '4', '0', '0'), // unofficial fourcc
|
||||
FOURCC_H420 = FOURCC('H', '4', '2', '0'), // unofficial fourcc
|
||||
|
||||
// 14 Auxiliary aliases. CanonicalFourCC() maps these to canonical fourcc.
|
||||
FOURCC_IYUV = FOURCC('I', 'Y', 'U', 'V'), // Alias for I420.
|
||||
FOURCC_YU16 = FOURCC('Y', 'U', '1', '6'), // Alias for I422.
|
||||
FOURCC_YU24 = FOURCC('Y', 'U', '2', '4'), // Alias for I444.
|
||||
FOURCC_YUYV = FOURCC('Y', 'U', 'Y', 'V'), // Alias for YUY2.
|
||||
FOURCC_YUVS = FOURCC('y', 'u', 'v', 's'), // Alias for YUY2 on Mac.
|
||||
FOURCC_HDYC = FOURCC('H', 'D', 'Y', 'C'), // Alias for UYVY.
|
||||
FOURCC_2VUY = FOURCC('2', 'v', 'u', 'y'), // Alias for UYVY on Mac.
|
||||
FOURCC_JPEG = FOURCC('J', 'P', 'E', 'G'), // Alias for MJPG.
|
||||
FOURCC_DMB1 = FOURCC('d', 'm', 'b', '1'), // Alias for MJPG on Mac.
|
||||
FOURCC_BA81 = FOURCC('B', 'A', '8', '1'), // Alias for BGGR.
|
||||
FOURCC_RGB3 = FOURCC('R', 'G', 'B', '3'), // Alias for RAW.
|
||||
FOURCC_BGR3 = FOURCC('B', 'G', 'R', '3'), // Alias for 24BG.
|
||||
FOURCC_CM32 = FOURCC(0, 0, 0, 32), // Alias for BGRA kCMPixelFormat_32ARGB
|
||||
FOURCC_CM24 = FOURCC(0, 0, 0, 24), // Alias for RAW kCMPixelFormat_24RGB
|
||||
FOURCC_L555 = FOURCC('L', '5', '5', '5'), // Alias for RGBO.
|
||||
FOURCC_L565 = FOURCC('L', '5', '6', '5'), // Alias for RGBP.
|
||||
FOURCC_5551 = FOURCC('5', '5', '5', '1'), // Alias for RGBO.
|
||||
|
||||
// 1 Auxiliary compressed YUV format set aside for capturer.
|
||||
FOURCC_H264 = FOURCC('H', '2', '6', '4'),
|
||||
|
||||
// Match any fourcc.
|
||||
FOURCC_ANY = -1,
|
||||
};
|
||||
|
||||
enum FourCCBpp {
|
||||
// Canonical fourcc codes used in our code.
|
||||
FOURCC_BPP_I420 = 12,
|
||||
FOURCC_BPP_I422 = 16,
|
||||
FOURCC_BPP_I444 = 24,
|
||||
FOURCC_BPP_I411 = 12,
|
||||
FOURCC_BPP_I400 = 8,
|
||||
FOURCC_BPP_NV21 = 12,
|
||||
FOURCC_BPP_NV12 = 12,
|
||||
FOURCC_BPP_YUY2 = 16,
|
||||
FOURCC_BPP_UYVY = 16,
|
||||
FOURCC_BPP_M420 = 12,
|
||||
FOURCC_BPP_Q420 = 12,
|
||||
FOURCC_BPP_ARGB = 32,
|
||||
FOURCC_BPP_BGRA = 32,
|
||||
FOURCC_BPP_ABGR = 32,
|
||||
FOURCC_BPP_RGBA = 32,
|
||||
FOURCC_BPP_24BG = 24,
|
||||
FOURCC_BPP_RAW = 24,
|
||||
FOURCC_BPP_RGBP = 16,
|
||||
FOURCC_BPP_RGBO = 16,
|
||||
FOURCC_BPP_R444 = 16,
|
||||
FOURCC_BPP_RGGB = 8,
|
||||
FOURCC_BPP_BGGR = 8,
|
||||
FOURCC_BPP_GRBG = 8,
|
||||
FOURCC_BPP_GBRG = 8,
|
||||
FOURCC_BPP_YV12 = 12,
|
||||
FOURCC_BPP_YV16 = 16,
|
||||
FOURCC_BPP_YV24 = 24,
|
||||
FOURCC_BPP_YU12 = 12,
|
||||
FOURCC_BPP_J420 = 12,
|
||||
FOURCC_BPP_J400 = 8,
|
||||
FOURCC_BPP_H420 = 12,
|
||||
FOURCC_BPP_MJPG = 0, // 0 means unknown.
|
||||
FOURCC_BPP_H264 = 0,
|
||||
FOURCC_BPP_IYUV = 12,
|
||||
FOURCC_BPP_YU16 = 16,
|
||||
FOURCC_BPP_YU24 = 24,
|
||||
FOURCC_BPP_YUYV = 16,
|
||||
FOURCC_BPP_YUVS = 16,
|
||||
FOURCC_BPP_HDYC = 16,
|
||||
FOURCC_BPP_2VUY = 16,
|
||||
FOURCC_BPP_JPEG = 1,
|
||||
FOURCC_BPP_DMB1 = 1,
|
||||
FOURCC_BPP_BA81 = 8,
|
||||
FOURCC_BPP_RGB3 = 24,
|
||||
FOURCC_BPP_BGR3 = 24,
|
||||
FOURCC_BPP_CM32 = 32,
|
||||
FOURCC_BPP_CM24 = 24,
|
||||
|
||||
// Match any fourcc.
|
||||
FOURCC_BPP_ANY = 0, // 0 means unknown.
|
||||
};
|
||||
|
||||
// Converts fourcc aliases into canonical ones.
|
||||
LIBYUV_API uint32 CanonicalFourCC(uint32 fourcc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace libyuv
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_LIBYUV_VIDEO_COMMON_H_
|
||||
BIN
third_party/libyuv/larch64/lib/libyuv.a
LFS
vendored
BIN
third_party/libyuv/larch64/lib/libyuv.a
LFS
vendored
Binary file not shown.
BIN
third_party/libyuv/x86_64/lib/libyuv.a
LFS
vendored
BIN
third_party/libyuv/x86_64/lib/libyuv.a
LFS
vendored
Binary file not shown.
@@ -45,17 +45,17 @@ cabana --demo
|
||||
To load a specific route for replay, provide the route as an argument:
|
||||
|
||||
```shell
|
||||
cabana "a2a0ccea32023010|2023-07-27--13-01-19"
|
||||
cabana "5beb9b58bd12b691/0000010a--a51155e496"
|
||||
```
|
||||
|
||||
Replace "0ccea32023010|2023-07-27--13-01-19" with your desired route identifier.
|
||||
Replace "5beb9b58bd12b691/0000010a--a51155e496" with your desired route identifier.
|
||||
|
||||
|
||||
### Running Cabana with multiple cameras
|
||||
To run Cabana with multiple cameras, use the following command:
|
||||
|
||||
```shell
|
||||
cabana "a2a0ccea32023010|2023-07-27--13-01-19" --dcam --ecam
|
||||
cabana "5beb9b58bd12b691/0000010a--a51155e496" --dcam --ecam
|
||||
```
|
||||
|
||||
### Streaming CAN Messages from a comma Device
|
||||
|
||||
@@ -81,7 +81,7 @@ if arch == "Darwin":
|
||||
cabana_env['CPPPATH'] += [f"{brew_prefix}/include"]
|
||||
cabana_env['LIBPATH'] += [f"{brew_prefix}/lib"]
|
||||
|
||||
cabana_libs = [cereal, messaging, visionipc, replay_lib, 'avformat', 'avcodec', 'swresample', 'avutil', 'x264', 'z', 'bz2', 'zstd', 'curl', 'yuv', 'usb-1.0'] + qt_libs
|
||||
cabana_libs = [cereal, messaging, visionipc, replay_lib, 'avformat', 'avcodec', 'swresample', 'avutil', 'x264', 'z', 'bz2', 'zstd', 'yuv', 'usb-1.0'] + qt_libs
|
||||
opendbc_path = '-DOPENDBC_FILE_PATH=\'"%s"\'' % (cabana_env.Dir("../../opendbc/dbc").abspath)
|
||||
cabana_env['CXXFLAGS'] += [opendbc_path]
|
||||
|
||||
@@ -93,7 +93,7 @@ cabana_env.Depends(assets, Glob('/assets/*', exclude=[assets, assets_src, "asset
|
||||
|
||||
cabana_lib = cabana_env.Library("cabana_lib", ['mainwin.cc', 'streams/socketcanstream.cc', 'streams/pandastream.cc', 'streams/devicestream.cc', 'streams/livestream.cc', 'streams/abstractstream.cc', 'streams/replaystream.cc', 'binaryview.cc', 'historylog.cc', 'videowidget.cc', 'signalview.cc',
|
||||
'streams/routes.cc', 'dbc/dbc.cc', 'dbc/dbcfile.cc', 'dbc/dbcmanager.cc',
|
||||
'utils/export.cc', 'utils/util.cc', 'utils/elidedlabel.cc', 'utils/api.cc',
|
||||
'utils/export.cc', 'utils/util.cc', 'utils/elidedlabel.cc',
|
||||
'chart/chartswidget.cc', 'chart/chart.cc', 'chart/signalselector.cc', 'chart/tiplabel.cc', 'chart/sparkline.cc',
|
||||
'commands.cc', 'messageswidget.cc', 'streamselector.cc', 'settings.cc', 'panda.cc',
|
||||
'cameraview.cc', 'detailwidget.cc', 'tools/findsimilarbits.cc', 'tools/findsignal.cc', 'tools/routeinfo.cc'], LIBS=cabana_libs, FRAMEWORKS=base_frameworks)
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "tools/cabana/streamselector.h"
|
||||
#include "tools/cabana/tools/findsignal.h"
|
||||
#include "tools/cabana/utils/export.h"
|
||||
#include "tools/replay/py_downloader.h"
|
||||
#include "tools/replay/util.h"
|
||||
|
||||
MainWindow::MainWindow(AbstractStream *stream, const QString &dbc_file) : QMainWindow() {
|
||||
loadFingerprints();
|
||||
|
||||
@@ -1,27 +1,33 @@
|
||||
#include "tools/cabana/streams/routes.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDateTime>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFormLayout>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QListWidget>
|
||||
#include <QMessageBox>
|
||||
#include <QPainter>
|
||||
#include <QPointer>
|
||||
#include <QtConcurrent>
|
||||
|
||||
class OneShotHttpRequest : public HttpRequest {
|
||||
public:
|
||||
OneShotHttpRequest(QObject *parent) : HttpRequest(parent, false) {}
|
||||
void send(const QString &url) {
|
||||
if (reply) {
|
||||
reply->disconnect();
|
||||
reply->abort();
|
||||
reply->deleteLater();
|
||||
reply = nullptr;
|
||||
}
|
||||
sendRequest(url);
|
||||
#include "tools/replay/py_downloader.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Parse a PyDownloader JSON response into (success, error_code).
|
||||
std::pair<bool, int> checkApiResponse(const std::string &result) {
|
||||
if (result.empty()) return {false, 500};
|
||||
auto doc = QJsonDocument::fromJson(QByteArray::fromStdString(result));
|
||||
if (doc.isObject() && doc.object().contains("error")) {
|
||||
return {false, doc.object()["error"].toString() == "unauthorized" ? 401 : 500};
|
||||
}
|
||||
};
|
||||
return {true, 0};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// The RouteListWidget class extends QListWidget to display a custom message when empty
|
||||
class RouteListWidget : public QListWidget {
|
||||
@@ -41,7 +47,7 @@ public:
|
||||
QString empty_text_ = tr("No items");
|
||||
};
|
||||
|
||||
RoutesDialog::RoutesDialog(QWidget *parent) : QDialog(parent), route_requester_(new OneShotHttpRequest(this)) {
|
||||
RoutesDialog::RoutesDialog(QWidget *parent) : QDialog(parent) {
|
||||
setWindowTitle(tr("Remote routes"));
|
||||
|
||||
QFormLayout *layout = new QFormLayout(this);
|
||||
@@ -52,41 +58,40 @@ RoutesDialog::RoutesDialog(QWidget *parent) : QDialog(parent), route_requester_(
|
||||
layout->addRow(button_box);
|
||||
|
||||
device_list_->addItem(tr("Loading..."));
|
||||
// Populate period selector with predefined durations
|
||||
period_selector_->addItem(tr("Last week"), 7);
|
||||
period_selector_->addItem(tr("Last 2 weeks"), 14);
|
||||
period_selector_->addItem(tr("Last month"), 30);
|
||||
period_selector_->addItem(tr("Last 6 months"), 180);
|
||||
period_selector_->addItem(tr("Preserved"), -1);
|
||||
|
||||
// Connect signals and slots
|
||||
QObject::connect(route_requester_, &HttpRequest::requestDone, this, &RoutesDialog::parseRouteList);
|
||||
connect(device_list_, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &RoutesDialog::fetchRoutes);
|
||||
connect(period_selector_, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &RoutesDialog::fetchRoutes);
|
||||
connect(route_list_, &QListWidget::itemDoubleClicked, this, &QDialog::accept);
|
||||
QObject::connect(button_box, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
QObject::connect(button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
connect(button_box, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
// Send request to fetch devices
|
||||
HttpRequest *http = new HttpRequest(this, false);
|
||||
QObject::connect(http, &HttpRequest::requestDone, this, &RoutesDialog::parseDeviceList);
|
||||
http->sendRequest(CommaApi::BASE_URL + "/v1/me/devices/");
|
||||
// Fetch devices
|
||||
QPointer<RoutesDialog> self = this;
|
||||
QtConcurrent::run([self]() {
|
||||
std::string result = PyDownloader::getDevices();
|
||||
auto [success, error_code] = checkApiResponse(result);
|
||||
QMetaObject::invokeMethod(qApp, [self, r = QString::fromStdString(result), success, error_code]() {
|
||||
if (self) self->parseDeviceList(r, success, error_code);
|
||||
}, Qt::QueuedConnection);
|
||||
});
|
||||
}
|
||||
|
||||
void RoutesDialog::parseDeviceList(const QString &json, bool success, QNetworkReply::NetworkError err) {
|
||||
void RoutesDialog::parseDeviceList(const QString &json, bool success, int error_code) {
|
||||
if (success) {
|
||||
device_list_->clear();
|
||||
auto devices = QJsonDocument::fromJson(json.toUtf8()).array();
|
||||
for (const QJsonValue &device : devices) {
|
||||
for (const QJsonValue &device : QJsonDocument::fromJson(json.toUtf8()).array()) {
|
||||
QString dongle_id = device["dongle_id"].toString();
|
||||
device_list_->addItem(dongle_id, dongle_id);
|
||||
}
|
||||
} else {
|
||||
bool unauthorized = (err == QNetworkReply::ContentAccessDenied || err == QNetworkReply::AuthenticationRequiredError);
|
||||
QMessageBox::warning(this, tr("Error"), unauthorized ? tr("Unauthorized, Authenticate with tools/lib/auth.py") : tr("Network error"));
|
||||
QMessageBox::warning(this, tr("Error"), error_code == 401 ? tr("Unauthorized. Authenticate with tools/lib/auth.py") : tr("Network error"));
|
||||
reject();
|
||||
}
|
||||
sender()->deleteLater();
|
||||
}
|
||||
|
||||
void RoutesDialog::fetchRoutes() {
|
||||
@@ -95,21 +100,31 @@ void RoutesDialog::fetchRoutes() {
|
||||
|
||||
route_list_->clear();
|
||||
route_list_->setEmptyText(tr("Loading..."));
|
||||
// Construct URL with selected device and date range
|
||||
QString url = QString("%1/v1/devices/%2").arg(CommaApi::BASE_URL, device_list_->currentText());
|
||||
|
||||
std::string did = device_list_->currentText().toStdString();
|
||||
int period = period_selector_->currentData().toInt();
|
||||
if (period == -1) {
|
||||
url += "/routes/preserved";
|
||||
} else {
|
||||
|
||||
bool preserved = (period == -1);
|
||||
int64_t start_ms = 0, end_ms = 0;
|
||||
if (!preserved) {
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
url += QString("/routes_segments?start=%1&end=%2")
|
||||
.arg(now.addDays(-period).toMSecsSinceEpoch())
|
||||
.arg(now.toMSecsSinceEpoch());
|
||||
start_ms = now.addDays(-period).toMSecsSinceEpoch();
|
||||
end_ms = now.toMSecsSinceEpoch();
|
||||
}
|
||||
route_requester_->send(url);
|
||||
|
||||
int request_id = ++fetch_id_;
|
||||
QPointer<RoutesDialog> self = this;
|
||||
QtConcurrent::run([self, did, start_ms, end_ms, preserved, request_id]() {
|
||||
std::string result = PyDownloader::getDeviceRoutes(did, start_ms, end_ms, preserved);
|
||||
if (!self || self->fetch_id_ != request_id) return;
|
||||
auto [success, error_code] = checkApiResponse(result);
|
||||
QMetaObject::invokeMethod(qApp, [self, r = QString::fromStdString(result), success, error_code, request_id]() {
|
||||
if (self && self->fetch_id_ == request_id) self->parseRouteList(r, success, error_code);
|
||||
}, Qt::QueuedConnection);
|
||||
});
|
||||
}
|
||||
|
||||
void RoutesDialog::parseRouteList(const QString &json, bool success, QNetworkReply::NetworkError err) {
|
||||
void RoutesDialog::parseRouteList(const QString &json, bool success, int error_code) {
|
||||
if (success) {
|
||||
for (const QJsonValue &route : QJsonDocument::fromJson(json.toUtf8()).array()) {
|
||||
QDateTime from, to;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <QComboBox>
|
||||
#include <QDialog>
|
||||
#include "tools/cabana/utils/api.h"
|
||||
|
||||
class RouteListWidget;
|
||||
class OneShotHttpRequest;
|
||||
|
||||
class RoutesDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
@@ -14,12 +13,12 @@ public:
|
||||
QString route();
|
||||
|
||||
protected:
|
||||
void parseDeviceList(const QString &json, bool success, QNetworkReply::NetworkError err);
|
||||
void parseRouteList(const QString &json, bool success, QNetworkReply::NetworkError err);
|
||||
void parseDeviceList(const QString &json, bool success, int error_code);
|
||||
void parseRouteList(const QString &json, bool success, int error_code);
|
||||
void fetchRoutes();
|
||||
|
||||
QComboBox *device_list_;
|
||||
QComboBox *period_selector_;
|
||||
RouteListWidget *route_list_;
|
||||
OneShotHttpRequest *route_requester_;
|
||||
std::atomic<int> fetch_id_{0};
|
||||
};
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
#include "tools/cabana/utils/api.h"
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QJsonDocument>
|
||||
#include <QNetworkRequest>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "common/params.h"
|
||||
#include "common/util.h"
|
||||
#include "system/hardware/hw.h"
|
||||
#include "tools/cabana/utils/util.h"
|
||||
|
||||
QString getVersion() {
|
||||
static QString version = QString::fromStdString(Params().get("Version"));
|
||||
return version;
|
||||
}
|
||||
|
||||
QString getUserAgent() {
|
||||
return "openpilot-" + getVersion();
|
||||
}
|
||||
|
||||
std::optional<QString> getDongleId() {
|
||||
std::string id = Params().get("DongleId");
|
||||
|
||||
if (!id.empty() && (id != "UnregisteredDevice")) {
|
||||
return QString::fromStdString(id);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
namespace CommaApi {
|
||||
|
||||
EVP_PKEY *get_private_key() {
|
||||
static std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> pkey(nullptr, EVP_PKEY_free);
|
||||
if (!pkey) {
|
||||
FILE *fp = fopen(Path::rsa_file().c_str(), "rb");
|
||||
if (!fp) {
|
||||
qDebug() << "No private key found, please run manager.py or registration.py";
|
||||
return nullptr;
|
||||
}
|
||||
pkey.reset(PEM_read_PrivateKey(fp, nullptr, nullptr, nullptr));
|
||||
fclose(fp);
|
||||
}
|
||||
return pkey.get();
|
||||
}
|
||||
|
||||
QByteArray rsa_sign(const QByteArray &data) {
|
||||
EVP_PKEY *pkey = get_private_key();
|
||||
if (!pkey) return {};
|
||||
|
||||
EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
|
||||
if (!mdctx) return {};
|
||||
|
||||
QByteArray sig(EVP_PKEY_size(pkey), Qt::Uninitialized);
|
||||
size_t sig_len = sig.size();
|
||||
|
||||
int ret = EVP_DigestSignInit(mdctx, nullptr, EVP_sha256(), nullptr, pkey);
|
||||
ret &= EVP_DigestSignUpdate(mdctx, data.data(), data.size());
|
||||
ret &= EVP_DigestSignFinal(mdctx, (unsigned char*)sig.data(), &sig_len);
|
||||
|
||||
EVP_MD_CTX_free(mdctx);
|
||||
|
||||
if (ret != 1) return {};
|
||||
sig.resize(sig_len);
|
||||
return sig;
|
||||
}
|
||||
|
||||
QString create_jwt(const QJsonObject &payloads, int expiry) {
|
||||
QJsonObject header = {{"alg", "RS256"}};
|
||||
|
||||
auto t = QDateTime::currentSecsSinceEpoch();
|
||||
QJsonObject payload = {{"identity", getDongleId().value_or("")}, {"nbf", t}, {"iat", t}, {"exp", t + expiry}};
|
||||
for (auto it = payloads.begin(); it != payloads.end(); ++it) {
|
||||
payload.insert(it.key(), it.value());
|
||||
}
|
||||
|
||||
auto b64_opts = QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals;
|
||||
QString jwt = QJsonDocument(header).toJson(QJsonDocument::Compact).toBase64(b64_opts) + '.' +
|
||||
QJsonDocument(payload).toJson(QJsonDocument::Compact).toBase64(b64_opts);
|
||||
|
||||
auto hash = QCryptographicHash::hash(jwt.toUtf8(), QCryptographicHash::Sha256);
|
||||
return jwt + "." + rsa_sign(hash).toBase64(b64_opts);
|
||||
}
|
||||
|
||||
} // namespace CommaApi
|
||||
|
||||
HttpRequest::HttpRequest(QObject *parent, bool create_jwt, int timeout) : create_jwt(create_jwt), QObject(parent) {
|
||||
networkTimer = new QTimer(this);
|
||||
networkTimer->setSingleShot(true);
|
||||
networkTimer->setInterval(timeout);
|
||||
connect(networkTimer, &QTimer::timeout, this, &HttpRequest::requestTimeout);
|
||||
}
|
||||
|
||||
bool HttpRequest::active() const {
|
||||
return reply != nullptr;
|
||||
}
|
||||
|
||||
bool HttpRequest::timeout() const {
|
||||
return reply && reply->error() == QNetworkReply::OperationCanceledError;
|
||||
}
|
||||
|
||||
void HttpRequest::sendRequest(const QString &requestURL, const HttpRequest::Method method) {
|
||||
if (active()) {
|
||||
qDebug() << "HttpRequest is active";
|
||||
return;
|
||||
}
|
||||
QString token;
|
||||
if (create_jwt) {
|
||||
token = CommaApi::create_jwt();
|
||||
} else {
|
||||
QString token_json = QString::fromStdString(util::read_file(util::getenv("HOME") + "/.comma/auth.json"));
|
||||
QJsonDocument json_d = QJsonDocument::fromJson(token_json.toUtf8());
|
||||
token = json_d["access_token"].toString();
|
||||
}
|
||||
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(requestURL));
|
||||
request.setRawHeader("User-Agent", getUserAgent().toUtf8());
|
||||
|
||||
if (!token.isEmpty()) {
|
||||
request.setRawHeader(QByteArray("Authorization"), ("JWT " + token).toUtf8());
|
||||
}
|
||||
|
||||
if (method == HttpRequest::Method::GET) {
|
||||
reply = nam()->get(request);
|
||||
} else if (method == HttpRequest::Method::DELETE) {
|
||||
reply = nam()->deleteResource(request);
|
||||
}
|
||||
|
||||
networkTimer->start();
|
||||
connect(reply, &QNetworkReply::finished, this, &HttpRequest::requestFinished);
|
||||
}
|
||||
|
||||
void HttpRequest::requestTimeout() {
|
||||
reply->abort();
|
||||
}
|
||||
|
||||
void HttpRequest::requestFinished() {
|
||||
networkTimer->stop();
|
||||
|
||||
if (reply->error() == QNetworkReply::NoError) {
|
||||
emit requestDone(reply->readAll(), true, reply->error());
|
||||
} else {
|
||||
QString error;
|
||||
if (reply->error() == QNetworkReply::OperationCanceledError) {
|
||||
nam()->clearAccessCache();
|
||||
nam()->clearConnectionCache();
|
||||
error = "Request timed out";
|
||||
} else {
|
||||
error = reply->errorString();
|
||||
}
|
||||
emit requestDone(error, false, reply->error());
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
reply = nullptr;
|
||||
}
|
||||
|
||||
QNetworkAccessManager *HttpRequest::nam() {
|
||||
static QNetworkAccessManager *networkAccessManager = new QNetworkAccessManager(qApp);
|
||||
return networkAccessManager;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QNetworkReply>
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
|
||||
#include "common/util.h"
|
||||
|
||||
namespace CommaApi {
|
||||
|
||||
const QString BASE_URL = util::getenv("API_HOST", "https://api.commadotai.com").c_str();
|
||||
QByteArray rsa_sign(const QByteArray &data);
|
||||
QString create_jwt(const QJsonObject &payloads = {}, int expiry = 3600);
|
||||
|
||||
} // namespace CommaApi
|
||||
|
||||
/**
|
||||
* Makes a request to the request endpoint.
|
||||
*/
|
||||
|
||||
class HttpRequest : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum class Method {GET, DELETE};
|
||||
|
||||
explicit HttpRequest(QObject* parent, bool create_jwt = true, int timeout = 20000);
|
||||
void sendRequest(const QString &requestURL, const Method method = Method::GET);
|
||||
bool active() const;
|
||||
bool timeout() const;
|
||||
|
||||
signals:
|
||||
void requestDone(const QString &response, bool success, QNetworkReply::NetworkError error);
|
||||
|
||||
protected:
|
||||
QNetworkReply *reply = nullptr;
|
||||
|
||||
private:
|
||||
static QNetworkAccessManager *nam();
|
||||
QTimer *networkTimer = nullptr;
|
||||
bool create_jwt;
|
||||
|
||||
private slots:
|
||||
void requestTimeout();
|
||||
void requestFinished();
|
||||
};
|
||||
@@ -24,7 +24,7 @@ from openpilot.common.utils import Timer
|
||||
from msgq.visionipc import VisionIpcServer, VisionStreamType
|
||||
|
||||
FRAMERATE = 20
|
||||
DEMO_ROUTE, DEMO_START, DEMO_END = 'a2a0ccea32023010/2023-07-27--13-01-19', 90, 105
|
||||
DEMO_ROUTE, DEMO_START, DEMO_END = '5beb9b58bd12b691/0000010a--a51155e496', 90, 105
|
||||
|
||||
logger = logging.getLogger('clip')
|
||||
|
||||
|
||||
@@ -21,17 +21,17 @@ options:
|
||||
|
||||
Example using route name:
|
||||
|
||||
`./pluggle.py "a2a0ccea32023010/2023-07-27--13-01-19"`
|
||||
`./pluggle.py "5beb9b58bd12b691/0000010a--a51155e496"`
|
||||
|
||||
Examples using segment:
|
||||
|
||||
`./pluggle.py "a2a0ccea32023010/2023-07-27--13-01-19/1"`
|
||||
`./pluggle.py "5beb9b58bd12b691/0000010a--a51155e496/1"`
|
||||
|
||||
`./pluggle.py "a2a0ccea32023010/2023-07-27--13-01-19/1/q" # use qlogs`
|
||||
`./pluggle.py "5beb9b58bd12b691/0000010a--a51155e496/1/q" # use qlogs`
|
||||
|
||||
Example using segment range:
|
||||
|
||||
`./pluggle.py "a2a0ccea32023010/2023-07-27--13-01-19/0:1"`
|
||||
`./pluggle.py "5beb9b58bd12b691/0000010a--a51155e496/0:1"`
|
||||
|
||||
## Demo
|
||||
|
||||
@@ -41,7 +41,7 @@ For a quick demo, run this command:
|
||||
|
||||
|
||||
## Basic Usage/Features:
|
||||
- The text box to load a route is a the top left of the page, accepts standard openpilot format routes (e.g. `a2a0ccea32023010/2023-07-27--13-01-19/0:1`, `https://connect.comma.ai/a2a0ccea32023010/2023-07-27--13-01-19/`)
|
||||
- The text box to load a route is a the top left of the page, accepts standard openpilot format routes (e.g. `5beb9b58bd12b691/0000010a--a51155e496/0:1`, `https://connect.comma.ai/5beb9b58bd12b691/0000010a--a51155e496/`)
|
||||
- The Play/Pause button is at the bottom of the screen, you can drag the bottom slider to seek. The timeline in timeseries plots are synced with the slider.
|
||||
- The Timeseries List sidebar has several dropdowns, the fields each show the field name and value, synced with the timeline (will show N/A until the time of the first message in that field is reached).
|
||||
- There is a search bar for the timeseries list, you can search for structs or fields, or both by separating with a "/"
|
||||
|
||||
@@ -12,7 +12,7 @@ from openpilot.tools.jotpluggler.data import DataManager
|
||||
from openpilot.tools.jotpluggler.datatree import DataTree
|
||||
from openpilot.tools.jotpluggler.layout import LayoutManager
|
||||
|
||||
DEMO_ROUTE = "a2a0ccea32023010|2023-07-27--13-01-19"
|
||||
DEMO_ROUTE = "5beb9b58bd12b691/0000010a--a51155e496"
|
||||
|
||||
|
||||
class WorkerManager:
|
||||
|
||||
148
tools/lib/file_downloader.py
Executable file
148
tools/lib/file_downloader.py
Executable file
@@ -0,0 +1,148 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
CLI tool for downloading files and querying the comma API.
|
||||
Called by C++ replay/cabana via subprocess.
|
||||
|
||||
Subcommands:
|
||||
route-files <route> - Get route file URLs as JSON
|
||||
download <url> - Download URL to local cache, print local path
|
||||
devices - List user's devices as JSON
|
||||
device-routes <did> - List routes for a device as JSON
|
||||
"""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
from openpilot.system.hardware.hw import Paths
|
||||
from openpilot.tools.lib.api import CommaApi, UnauthorizedError, APIError
|
||||
from openpilot.tools.lib.auth_config import get_token
|
||||
from openpilot.tools.lib.url_file import URLFile
|
||||
|
||||
|
||||
def api_call(func):
|
||||
"""Run an API call, outputting JSON result or error to stdout."""
|
||||
try:
|
||||
result = func(CommaApi(get_token()))
|
||||
json.dump(result, sys.stdout)
|
||||
except UnauthorizedError:
|
||||
json.dump({"error": "unauthorized"}, sys.stdout)
|
||||
except APIError as e:
|
||||
error = "not_found" if getattr(e, 'status_code', 0) == 404 else str(e)
|
||||
json.dump({"error": error}, sys.stdout)
|
||||
except Exception as e:
|
||||
json.dump({"error": str(e)}, sys.stdout)
|
||||
sys.stdout.write("\n")
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def cache_file_path(url):
|
||||
url_without_query = url.split("?")[0]
|
||||
return os.path.join(Paths.download_cache_root(), hashlib.sha256(url_without_query.encode()).hexdigest())
|
||||
|
||||
|
||||
def cmd_route_files(args):
|
||||
api_call(lambda api: api.get(f"v1/route/{args.route}/files"))
|
||||
|
||||
|
||||
def cmd_download(args):
|
||||
url = args.url
|
||||
use_cache = not args.no_cache
|
||||
|
||||
if use_cache:
|
||||
local_path = cache_file_path(url)
|
||||
if os.path.exists(local_path):
|
||||
sys.stdout.write(local_path + "\n")
|
||||
sys.stdout.flush()
|
||||
return
|
||||
|
||||
try:
|
||||
uf = URLFile(url, cache=False)
|
||||
total = uf.get_length()
|
||||
if total <= 0:
|
||||
sys.stderr.write("ERROR:File not found or empty\n")
|
||||
sys.stderr.flush()
|
||||
sys.exit(1)
|
||||
|
||||
os.makedirs(Paths.download_cache_root(), exist_ok=True)
|
||||
tmp_fd, tmp_path = tempfile.mkstemp(dir=Paths.download_cache_root())
|
||||
try:
|
||||
downloaded = 0
|
||||
chunk_size = 1024 * 1024
|
||||
with os.fdopen(tmp_fd, 'wb') as f:
|
||||
while downloaded < total:
|
||||
data = uf.read(min(chunk_size, total - downloaded))
|
||||
f.write(data)
|
||||
downloaded += len(data)
|
||||
sys.stderr.write(f"PROGRESS:{downloaded}:{total}\n")
|
||||
sys.stderr.flush()
|
||||
|
||||
if use_cache:
|
||||
shutil.move(tmp_path, local_path)
|
||||
sys.stdout.write(local_path + "\n")
|
||||
else:
|
||||
sys.stdout.write(tmp_path + "\n")
|
||||
except Exception:
|
||||
try:
|
||||
os.unlink(tmp_path)
|
||||
except OSError:
|
||||
pass
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
sys.stderr.write(f"ERROR:{e}\n")
|
||||
sys.stderr.flush()
|
||||
sys.exit(1)
|
||||
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def cmd_devices(args):
|
||||
api_call(lambda api: api.get("v1/me/devices/"))
|
||||
|
||||
|
||||
def cmd_device_routes(args):
|
||||
def fetch(api):
|
||||
if args.preserved:
|
||||
return api.get(f"v1/devices/{args.dongle_id}/routes/preserved")
|
||||
params = {}
|
||||
if args.start is not None:
|
||||
params['start'] = args.start
|
||||
if args.end is not None:
|
||||
params['end'] = args.end
|
||||
return api.get(f"v1/devices/{args.dongle_id}/routes_segments", params=params)
|
||||
api_call(fetch)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="File downloader CLI for openpilot tools")
|
||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
p_rf = subparsers.add_parser("route-files")
|
||||
p_rf.add_argument("route")
|
||||
p_rf.set_defaults(func=cmd_route_files)
|
||||
|
||||
p_dl = subparsers.add_parser("download")
|
||||
p_dl.add_argument("url")
|
||||
p_dl.add_argument("--no-cache", action="store_true")
|
||||
p_dl.set_defaults(func=cmd_download)
|
||||
|
||||
p_dev = subparsers.add_parser("devices")
|
||||
p_dev.set_defaults(func=cmd_devices)
|
||||
|
||||
p_dr = subparsers.add_parser("device-routes")
|
||||
p_dr.add_argument("dongle_id")
|
||||
p_dr.add_argument("--start", type=int, default=None)
|
||||
p_dr.add_argument("--end", type=int, default=None)
|
||||
p_dr.add_argument("--preserved", action="store_true")
|
||||
p_dr.set_defaults(func=cmd_device_routes)
|
||||
|
||||
args = parser.parse_args()
|
||||
args.func(args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -35,17 +35,17 @@ optional arguments:
|
||||
|
||||
Example using route name:
|
||||
|
||||
`./juggle.py "a2a0ccea32023010/2023-07-27--13-01-19"`
|
||||
`./juggle.py "5beb9b58bd12b691/0000010a--a51155e496"`
|
||||
|
||||
Examples using segment:
|
||||
|
||||
`./juggle.py "a2a0ccea32023010/2023-07-27--13-01-19/1"`
|
||||
`./juggle.py "5beb9b58bd12b691/0000010a--a51155e496/1"`
|
||||
|
||||
`./juggle.py "a2a0ccea32023010/2023-07-27--13-01-19/1/q" # use qlogs`
|
||||
`./juggle.py "5beb9b58bd12b691/0000010a--a51155e496/1/q" # use qlogs`
|
||||
|
||||
Example using segment range:
|
||||
|
||||
`./juggle.py "a2a0ccea32023010/2023-07-27--13-01-19/0:1"`
|
||||
`./juggle.py "5beb9b58bd12b691/0000010a--a51155e496/0:1"`
|
||||
|
||||
## Streaming
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ juggle_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
os.environ['LD_LIBRARY_PATH'] = os.environ.get('LD_LIBRARY_PATH', '') + f":{juggle_dir}/bin/"
|
||||
|
||||
DEMO_ROUTE = "a2a0ccea32023010|2023-07-27--13-01-19"
|
||||
DEMO_ROUTE = "5beb9b58bd12b691/0000010a--a51155e496"
|
||||
RELEASES_URL = "https://github.com/commaai/PlotJuggler/releases/download/latest"
|
||||
INSTALL_DIR = os.path.join(juggle_dir, "bin")
|
||||
PLOTJUGGLER_BIN = os.path.join(juggle_dir, "bin/plotjuggler")
|
||||
|
||||
@@ -19,7 +19,7 @@ You can replay a route from your comma account by specifying the route name.
|
||||
tools/replay/replay <route-name>
|
||||
|
||||
# Example:
|
||||
tools/replay/replay 'a2a0ccea32023010|2023-07-27--13-01-19'
|
||||
tools/replay/replay '5beb9b58bd12b691/0000010a--a51155e496'
|
||||
|
||||
# Replay the default demo route:
|
||||
tools/replay/replay --demo
|
||||
@@ -34,10 +34,10 @@ tools/replay/replay <route-name> --data_dir="/path_to/route"
|
||||
|
||||
# Example:
|
||||
# If you have a local route stored at /path_to_routes with segments like:
|
||||
# a2a0ccea32023010|2023-07-27--13-01-19--0
|
||||
# a2a0ccea32023010|2023-07-27--13-01-19--1
|
||||
# 5beb9b58bd12b691/0000010a--a51155e496--0
|
||||
# 5beb9b58bd12b691/0000010a--a51155e496--1
|
||||
# You can replay it like this:
|
||||
tools/replay/replay "a2a0ccea32023010|2023-07-27--13-01-19" --data_dir="/path_to_routes"
|
||||
tools/replay/replay "5beb9b58bd12b691/0000010a--a51155e496" --data_dir="/path_to_routes"
|
||||
```
|
||||
|
||||
## Send Messages via ZMQ
|
||||
|
||||
@@ -7,12 +7,12 @@ base_frameworks = []
|
||||
base_libs = [common, messaging, cereal, visionipc, 'm', 'ssl', 'crypto', 'pthread']
|
||||
|
||||
replay_lib_src = ["replay.cc", "consoleui.cc", "camera.cc", "filereader.cc", "logreader.cc", "framereader.cc",
|
||||
"route.cc", "util.cc", "seg_mgr.cc", "timeline.cc", "api.cc"]
|
||||
"route.cc", "util.cc", "seg_mgr.cc", "timeline.cc", "py_downloader.cc"]
|
||||
if arch != "Darwin":
|
||||
replay_lib_src.append("qcom_decoder.cc")
|
||||
replay_lib = replay_env.Library("replay", replay_lib_src, LIBS=base_libs, FRAMEWORKS=base_frameworks)
|
||||
Export('replay_lib')
|
||||
replay_libs = [replay_lib, 'avformat', 'avcodec', 'swresample', 'avutil', 'x264', 'z', 'bz2', 'zstd', 'curl', 'yuv', 'ncurses'] + base_libs
|
||||
replay_libs = [replay_lib, 'avformat', 'avcodec', 'swresample', 'avutil', 'x264', 'z', 'bz2', 'zstd', 'yuv', 'ncurses'] + base_libs
|
||||
replay_env.Program("replay", ["main.cc"], LIBS=replay_libs, FRAMEWORKS=base_frameworks)
|
||||
|
||||
if GetOption('extras'):
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
|
||||
#include "tools/replay/api.h"
|
||||
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
#include "common/params.h"
|
||||
#include "common/version.h"
|
||||
#include "system/hardware/hw.h"
|
||||
|
||||
#include "sunnypilot/common/version.h"
|
||||
|
||||
namespace CommaApi2 {
|
||||
|
||||
// Base64 URL-safe character set (uses '-' and '_' instead of '+' and '/')
|
||||
static const std::string base64url_chars =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789-_";
|
||||
|
||||
std::string base64url_encode(const std::string &in) {
|
||||
std::string out;
|
||||
int val = 0, valb = -6;
|
||||
for (unsigned char c : in) {
|
||||
val = (val << 8) + c;
|
||||
valb += 8;
|
||||
while (valb >= 0) {
|
||||
out.push_back(base64url_chars[(val >> valb) & 0x3F]);
|
||||
valb -= 6;
|
||||
}
|
||||
}
|
||||
if (valb > -6) {
|
||||
out.push_back(base64url_chars[((val << 8) >> (valb + 8)) & 0x3F]);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
EVP_PKEY *get_rsa_private_key() {
|
||||
static std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> rsa_private(nullptr, EVP_PKEY_free);
|
||||
if (!rsa_private) {
|
||||
FILE *fp = fopen(Path::rsa_file().c_str(), "rb");
|
||||
if (!fp) {
|
||||
std::cerr << "No RSA private key found, please run manager.py or registration.py" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
rsa_private.reset(PEM_read_PrivateKey(fp, NULL, NULL, NULL));
|
||||
fclose(fp);
|
||||
}
|
||||
return rsa_private.get();
|
||||
}
|
||||
|
||||
std::string rsa_sign(const std::string &data) {
|
||||
EVP_PKEY *private_key = get_rsa_private_key();
|
||||
if (!private_key) return {};
|
||||
|
||||
EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
|
||||
assert(mdctx != nullptr);
|
||||
|
||||
std::vector<uint8_t> sig(EVP_PKEY_size(private_key));
|
||||
uint32_t sig_len;
|
||||
|
||||
EVP_SignInit(mdctx, EVP_sha256());
|
||||
EVP_SignUpdate(mdctx, data.data(), data.size());
|
||||
int ret = EVP_SignFinal(mdctx, sig.data(), &sig_len, private_key);
|
||||
|
||||
EVP_MD_CTX_free(mdctx);
|
||||
|
||||
assert(ret == 1);
|
||||
assert(sig.size() == sig_len);
|
||||
return std::string(sig.begin(), sig.begin() + sig_len);
|
||||
}
|
||||
|
||||
std::string create_jwt(const json11::Json &extra, int exp_time) {
|
||||
int now = std::chrono::seconds(std::time(nullptr)).count();
|
||||
std::string dongle_id = Params().get("DongleId");
|
||||
|
||||
// Create header and payload
|
||||
json11::Json header = json11::Json::object{{"alg", "RS256"}};
|
||||
auto payload = json11::Json::object{
|
||||
{"identity", dongle_id},
|
||||
{"iat", now},
|
||||
{"nbf", now},
|
||||
{"exp", now + exp_time},
|
||||
};
|
||||
// Merge extra payload
|
||||
for (const auto &item : extra.object_items()) {
|
||||
payload[item.first] = item.second;
|
||||
}
|
||||
|
||||
// JWT construction
|
||||
std::string jwt = base64url_encode(header.dump()) + '.' +
|
||||
base64url_encode(json11::Json(payload).dump());
|
||||
|
||||
// Hash and sign
|
||||
std::string hash(SHA256_DIGEST_LENGTH, '\0');
|
||||
SHA256((uint8_t *)jwt.data(), jwt.size(), (uint8_t *)hash.data());
|
||||
std::string signature = rsa_sign(hash);
|
||||
|
||||
return jwt + "." + base64url_encode(signature);
|
||||
}
|
||||
|
||||
std::string create_token(bool use_jwt, const json11::Json &payloads, int expiry) {
|
||||
if (use_jwt) {
|
||||
return create_jwt(payloads, expiry);
|
||||
}
|
||||
|
||||
std::string token_json = util::read_file(util::getenv("HOME") + "/.comma/auth.json");
|
||||
std::string err;
|
||||
auto json = json11::Json::parse(token_json, err);
|
||||
if (!err.empty()) {
|
||||
std::cerr << "Error parsing auth.json " << err << std::endl;
|
||||
return "";
|
||||
}
|
||||
return json["access_token"].string_value();
|
||||
}
|
||||
|
||||
std::string httpGet(const std::string &url, long *response_code) {
|
||||
CURL *curl = curl_easy_init();
|
||||
assert(curl);
|
||||
|
||||
std::string readBuffer;
|
||||
const std::string token = CommaApi2::create_token(!Hardware::PC());
|
||||
|
||||
// Set up the lambda for the write callback
|
||||
// The '+' makes the lambda non-capturing, allowing it to be used as a C function pointer
|
||||
auto writeCallback = +[](char *contents, size_t size, size_t nmemb, std::string *userp) ->size_t{
|
||||
size_t totalSize = size * nmemb;
|
||||
userp->append((char *)contents, totalSize);
|
||||
return totalSize;
|
||||
};
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
|
||||
// Handle headers
|
||||
struct curl_slist *headers = nullptr;
|
||||
headers = curl_slist_append(headers, "User-Agent: openpilot-" SUNNYPILOT_VERSION);
|
||||
if (!token.empty()) {
|
||||
headers = curl_slist_append(headers, ("Authorization: JWT " + token).c_str());
|
||||
}
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
|
||||
if (response_code) {
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, response_code);
|
||||
}
|
||||
|
||||
curl_slist_free_all(headers);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
return res == CURLE_OK ? readBuffer : std::string{};
|
||||
}
|
||||
|
||||
} // namespace CommaApi
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <string>
|
||||
|
||||
#include "common/util.h"
|
||||
#include "third_party/json11/json11.hpp"
|
||||
|
||||
namespace CommaApi2 {
|
||||
|
||||
const std::string BASE_URL = util::getenv("API_HOST", "https://api.commadotai.com").c_str();
|
||||
std::string create_token(bool use_jwt, const json11::Json& payloads = {}, int expiry = 3600);
|
||||
std::string httpGet(const std::string &url, long *response_code = nullptr);
|
||||
|
||||
} // namespace CommaApi2
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "common/ratekeeper.h"
|
||||
#include "common/util.h"
|
||||
#include "common/version.h"
|
||||
#include "tools/replay/py_downloader.h"
|
||||
|
||||
#include "sunnypilot/common/version.h"
|
||||
|
||||
|
||||
@@ -1,49 +1,14 @@
|
||||
#include "tools/replay/filereader.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "common/util.h"
|
||||
#include "system/hardware/hw.h"
|
||||
#include "tools/replay/util.h"
|
||||
|
||||
std::string cacheFilePath(const std::string &url) {
|
||||
static std::string cache_path = [] {
|
||||
const std::string comma_cache = Path::download_cache_root();
|
||||
util::create_directories(comma_cache, 0755);
|
||||
return comma_cache.back() == '/' ? comma_cache : comma_cache + "/";
|
||||
}();
|
||||
|
||||
return cache_path + sha256(getUrlWithoutQuery(url));
|
||||
}
|
||||
#include "tools/replay/py_downloader.h"
|
||||
|
||||
std::string FileReader::read(const std::string &file, std::atomic<bool> *abort) {
|
||||
const bool is_remote = (file.find("https://") == 0) || (file.find("http://") == 0);
|
||||
const std::string local_file = is_remote ? cacheFilePath(file) : file;
|
||||
std::string result;
|
||||
|
||||
if ((!is_remote || cache_to_local_) && util::file_exists(local_file)) {
|
||||
result = util::read_file(local_file);
|
||||
} else if (is_remote) {
|
||||
result = download(file, abort);
|
||||
if (cache_to_local_ && !result.empty()) {
|
||||
std::ofstream fs(local_file, std::ios::binary | std::ios::out);
|
||||
fs.write(result.data(), result.size());
|
||||
}
|
||||
if (is_remote) {
|
||||
std::string local_path = PyDownloader::download(file, cache_to_local_, abort);
|
||||
if (local_path.empty()) return {};
|
||||
return util::read_file(local_path);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string FileReader::download(const std::string &url, std::atomic<bool> *abort) {
|
||||
for (int i = 0; i <= max_retries_ && !(abort && *abort); ++i) {
|
||||
if (i > 0) {
|
||||
rWarning("download failed, retrying %d", i);
|
||||
util::sleep_for(3000);
|
||||
}
|
||||
|
||||
std::string result = httpGet(url, chunk_size_, abort);
|
||||
if (!result.empty()) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
return util::read_file(file);
|
||||
}
|
||||
|
||||
@@ -5,16 +5,10 @@
|
||||
|
||||
class FileReader {
|
||||
public:
|
||||
FileReader(bool cache_to_local, size_t chunk_size = 0, int retries = 3)
|
||||
: cache_to_local_(cache_to_local), chunk_size_(chunk_size), max_retries_(retries) {}
|
||||
FileReader(bool cache_to_local) : cache_to_local_(cache_to_local) {}
|
||||
virtual ~FileReader() {}
|
||||
std::string read(const std::string &file, std::atomic<bool> *abort = nullptr);
|
||||
|
||||
private:
|
||||
std::string download(const std::string &url, std::atomic<bool> *abort);
|
||||
size_t chunk_size_;
|
||||
int max_retries_;
|
||||
bool cache_to_local_;
|
||||
};
|
||||
|
||||
std::string cacheFilePath(const std::string &url);
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
#include <utility>
|
||||
|
||||
#include "common/util.h"
|
||||
#include "third_party/libyuv/include/libyuv.h"
|
||||
#include "libyuv.h"
|
||||
#include "tools/replay/py_downloader.h"
|
||||
#include "tools/replay/util.h"
|
||||
#include "system/hardware/hw.h"
|
||||
|
||||
@@ -71,13 +72,13 @@ FrameReader::~FrameReader() {
|
||||
if (input_ctx) avformat_close_input(&input_ctx);
|
||||
}
|
||||
|
||||
bool FrameReader::load(CameraType type, const std::string &url, bool no_hw_decoder, std::atomic<bool> *abort, bool local_cache, int chunk_size, int retries) {
|
||||
auto local_file_path = (url.find("https://") == 0 || url.find("http://") == 0) ? cacheFilePath(url) : url;
|
||||
if (!util::file_exists(local_file_path)) {
|
||||
FileReader f(local_cache, chunk_size, retries);
|
||||
if (f.read(url, abort).empty()) {
|
||||
return false;
|
||||
}
|
||||
bool FrameReader::load(CameraType type, const std::string &url, bool no_hw_decoder, std::atomic<bool> *abort, bool local_cache) {
|
||||
std::string local_file_path;
|
||||
if (url.find("https://") == 0 || url.find("http://") == 0) {
|
||||
local_file_path = PyDownloader::download(url, local_cache, abort);
|
||||
if (local_file_path.empty()) return false;
|
||||
} else {
|
||||
local_file_path = url;
|
||||
}
|
||||
return loadFromFile(type, local_file_path, no_hw_decoder, abort);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "msgq/visionipc/visionbuf.h"
|
||||
#include "tools/replay/filereader.h"
|
||||
#include "tools/replay/util.h"
|
||||
|
||||
#ifndef __APPLE__
|
||||
@@ -22,8 +21,7 @@ class FrameReader {
|
||||
public:
|
||||
FrameReader();
|
||||
~FrameReader();
|
||||
bool load(CameraType type, const std::string &url, bool no_hw_decoder = false, std::atomic<bool> *abort = nullptr, bool local_cache = false,
|
||||
int chunk_size = -1, int retries = 0);
|
||||
bool load(CameraType type, const std::string &url, bool no_hw_decoder = false, std::atomic<bool> *abort = nullptr, bool local_cache = false);
|
||||
bool loadFromFile(CameraType type, const std::string &file, bool no_hw_decoder = false, std::atomic<bool> *abort = nullptr);
|
||||
bool get(int idx, VisionBuf *buf);
|
||||
size_t getFrameCount() const { return packets_info.size(); }
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#include "tools/replay/util.h"
|
||||
#include "common/util.h"
|
||||
|
||||
bool LogReader::load(const std::string &url, std::atomic<bool> *abort, bool local_cache, int chunk_size, int retries) {
|
||||
std::string data = FileReader(local_cache, chunk_size, retries).read(url, abort);
|
||||
bool LogReader::load(const std::string &url, std::atomic<bool> *abort, bool local_cache) {
|
||||
std::string data = FileReader(local_cache).read(url, abort);
|
||||
if (!data.empty()) {
|
||||
if (url.find(".bz2") != std::string::npos || util::starts_with(data, "BZh9")) {
|
||||
data = decompressBZ2(data, abort);
|
||||
|
||||
@@ -28,7 +28,7 @@ class LogReader {
|
||||
public:
|
||||
LogReader(const std::vector<bool> &filters = {}) { filters_ = filters; }
|
||||
bool load(const std::string &url, std::atomic<bool> *abort = nullptr,
|
||||
bool local_cache = false, int chunk_size = -1, int retries = 0);
|
||||
bool local_cache = false);
|
||||
bool load(const char *data, size_t size, std::atomic<bool> *abort = nullptr);
|
||||
std::vector<Event> events;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <getopt.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
@@ -132,6 +133,10 @@ int main(int argc, char *argv[]) {
|
||||
util::set_file_descriptor_limit(1024);
|
||||
#endif
|
||||
|
||||
// The vendored ncurses static library has a wrong compiled-in terminfo path.
|
||||
// Point it at the system terminfo database if not already set.
|
||||
setenv("TERMINFO_DIRS", "/usr/share/terminfo:/lib/terminfo:/usr/lib/terminfo", 0);
|
||||
|
||||
ReplayConfig config;
|
||||
|
||||
if (!parseArgs(argc, argv, config)) {
|
||||
|
||||
218
tools/replay/py_downloader.cc
Normal file
218
tools/replay/py_downloader.cc
Normal file
@@ -0,0 +1,218 @@
|
||||
#include "tools/replay/py_downloader.h"
|
||||
|
||||
#include <csignal>
|
||||
#include <fcntl.h>
|
||||
#include <mutex>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tools/replay/util.h"
|
||||
|
||||
namespace {
|
||||
|
||||
static std::mutex handler_mutex;
|
||||
static DownloadProgressHandler progress_handler = nullptr;
|
||||
|
||||
// Run a Python command and capture stdout. Optionally parse stderr for PROGRESS lines.
|
||||
// Returns stdout content. If abort is signaled, kills the child process.
|
||||
std::string runPython(const std::vector<std::string> &args, std::atomic<bool> *abort = nullptr, bool parse_progress = false) {
|
||||
// Build argv for execvp
|
||||
std::vector<const char *> argv;
|
||||
argv.push_back("python3");
|
||||
argv.push_back("-m");
|
||||
argv.push_back("openpilot.tools.lib.file_downloader");
|
||||
for (const auto &a : args) {
|
||||
argv.push_back(a.c_str());
|
||||
}
|
||||
argv.push_back(nullptr);
|
||||
|
||||
int stdout_pipe[2];
|
||||
int stderr_pipe[2];
|
||||
if (pipe(stdout_pipe) != 0) {
|
||||
rWarning("py_downloader: pipe() failed");
|
||||
return {};
|
||||
}
|
||||
if (pipe(stderr_pipe) != 0) {
|
||||
rWarning("py_downloader: pipe() failed");
|
||||
close(stdout_pipe[0]); close(stdout_pipe[1]);
|
||||
return {};
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
rWarning("py_downloader: fork() failed");
|
||||
close(stdout_pipe[0]); close(stdout_pipe[1]);
|
||||
close(stderr_pipe[0]); close(stderr_pipe[1]);
|
||||
return {};
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
// Child process — detach from controlling terminal so Python
|
||||
// cannot corrupt terminal settings needed by ncurses in the parent.
|
||||
setsid();
|
||||
int devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull >= 0) {
|
||||
dup2(devnull, STDIN_FILENO);
|
||||
if (devnull > STDERR_FILENO) close(devnull);
|
||||
}
|
||||
|
||||
// Clear OPENPILOT_PREFIX so the Python process uses default paths
|
||||
// (e.g. ~/.comma/auth.json). The prefix is only for IPC in the parent.
|
||||
unsetenv("OPENPILOT_PREFIX");
|
||||
|
||||
close(stdout_pipe[0]);
|
||||
close(stderr_pipe[0]);
|
||||
dup2(stdout_pipe[1], STDOUT_FILENO);
|
||||
dup2(stderr_pipe[1], STDERR_FILENO);
|
||||
close(stdout_pipe[1]);
|
||||
close(stderr_pipe[1]);
|
||||
|
||||
execvp("python3", const_cast<char *const *>(argv.data()));
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
// Parent process
|
||||
close(stdout_pipe[1]);
|
||||
close(stderr_pipe[1]);
|
||||
|
||||
std::string stdout_data;
|
||||
std::string stderr_buf;
|
||||
char buf[4096];
|
||||
|
||||
// Use select() to read from both pipes
|
||||
fd_set rfds;
|
||||
int max_fd = std::max(stdout_pipe[0], stderr_pipe[0]);
|
||||
bool stdout_open = true, stderr_open = true;
|
||||
|
||||
while (stdout_open || stderr_open) {
|
||||
if (abort && *abort) {
|
||||
kill(pid, SIGTERM);
|
||||
break;
|
||||
}
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
if (stdout_open) FD_SET(stdout_pipe[0], &rfds);
|
||||
if (stderr_open) FD_SET(stderr_pipe[0], &rfds);
|
||||
|
||||
struct timeval tv = {0, 100000}; // 100ms timeout
|
||||
int ret = select(max_fd + 1, &rfds, nullptr, nullptr, &tv);
|
||||
if (ret < 0) break;
|
||||
|
||||
if (stdout_open && FD_ISSET(stdout_pipe[0], &rfds)) {
|
||||
ssize_t n = read(stdout_pipe[0], buf, sizeof(buf));
|
||||
if (n <= 0) {
|
||||
stdout_open = false;
|
||||
} else {
|
||||
stdout_data.append(buf, n);
|
||||
}
|
||||
}
|
||||
|
||||
if (stderr_open && FD_ISSET(stderr_pipe[0], &rfds)) {
|
||||
ssize_t n = read(stderr_pipe[0], buf, sizeof(buf));
|
||||
if (n <= 0) {
|
||||
stderr_open = false;
|
||||
} else {
|
||||
stderr_buf.append(buf, n);
|
||||
// Parse complete lines from stderr
|
||||
size_t pos;
|
||||
while ((pos = stderr_buf.find('\n')) != std::string::npos) {
|
||||
std::string line = stderr_buf.substr(0, pos);
|
||||
stderr_buf.erase(0, pos + 1);
|
||||
|
||||
if (parse_progress && line.rfind("PROGRESS:", 0) == 0) {
|
||||
// Parse "PROGRESS:<cur>:<total>"
|
||||
auto colon1 = line.find(':', 9);
|
||||
if (colon1 != std::string::npos) {
|
||||
try {
|
||||
uint64_t cur = std::stoull(line.c_str() + 9);
|
||||
uint64_t total = std::stoull(line.c_str() + colon1 + 1);
|
||||
std::lock_guard<std::mutex> lk(handler_mutex);
|
||||
if (progress_handler) {
|
||||
progress_handler(cur, total, true);
|
||||
}
|
||||
} catch (...) {}
|
||||
}
|
||||
} else if (line.rfind("ERROR:", 0) == 0) {
|
||||
rWarning("py_downloader: %s", line.c_str() + 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Drain remaining pipe data to prevent child from blocking on write
|
||||
for (int fd : {stdout_pipe[0], stderr_pipe[0]}) {
|
||||
while (read(fd, buf, sizeof(buf)) > 0) {}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
|
||||
bool failed = (abort && *abort) ||
|
||||
(WIFEXITED(status) && WEXITSTATUS(status) != 0) ||
|
||||
WIFSIGNALED(status);
|
||||
if (failed) {
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
|
||||
rWarning("py_downloader: process exited with code %d", WEXITSTATUS(status));
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
rWarning("py_downloader: process killed by signal %d", WTERMSIG(status));
|
||||
}
|
||||
std::lock_guard<std::mutex> lk(handler_mutex);
|
||||
if (progress_handler) {
|
||||
progress_handler(0, 0, false);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// Trim trailing newline
|
||||
while (!stdout_data.empty() && (stdout_data.back() == '\n' || stdout_data.back() == '\r')) {
|
||||
stdout_data.pop_back();
|
||||
}
|
||||
|
||||
return stdout_data;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void installDownloadProgressHandler(DownloadProgressHandler handler) {
|
||||
std::lock_guard<std::mutex> lk(handler_mutex);
|
||||
progress_handler = handler;
|
||||
}
|
||||
|
||||
namespace PyDownloader {
|
||||
|
||||
std::string download(const std::string &url, bool use_cache, std::atomic<bool> *abort) {
|
||||
std::vector<std::string> args = {"download", url};
|
||||
if (!use_cache) {
|
||||
args.push_back("--no-cache");
|
||||
}
|
||||
return runPython(args, abort, true);
|
||||
}
|
||||
|
||||
std::string getRouteFiles(const std::string &route) {
|
||||
return runPython({"route-files", route});
|
||||
}
|
||||
|
||||
std::string getDevices() {
|
||||
return runPython({"devices"});
|
||||
}
|
||||
|
||||
std::string getDeviceRoutes(const std::string &dongle_id, int64_t start_ms, int64_t end_ms, bool preserved) {
|
||||
std::vector<std::string> args = {"device-routes", dongle_id};
|
||||
if (preserved) {
|
||||
args.push_back("--preserved");
|
||||
} else {
|
||||
if (start_ms > 0) {
|
||||
args.push_back("--start");
|
||||
args.push_back(std::to_string(start_ms));
|
||||
}
|
||||
if (end_ms > 0) {
|
||||
args.push_back("--end");
|
||||
args.push_back(std::to_string(end_ms));
|
||||
}
|
||||
}
|
||||
return runPython(args);
|
||||
}
|
||||
|
||||
} // namespace PyDownloader
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user