fix: dashcamd OMX crash on restart, add dashcam status indicator
Some checks failed
prebuilt / build prebuilt (push) Has been cancelled
badges / create badges (push) Has been cancelled

- Reset OMX subsystem (Deinit/Init) on dashcamd startup to clear stale
  encoder state from previous unclean exits
- Validate OMX output buffers before memcpy to prevent segfault
- Validate VisionBuf frame data before encoding
- Add dashcam row to status window showing recording state and disk usage

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-16 00:44:13 -05:00
parent 3cbb81f9f1
commit 9ac334b7cf
5 changed files with 39 additions and 0 deletions

Binary file not shown.

View File

@@ -118,6 +118,10 @@ static std::string srt_time(int seconds) {
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
setpriority(PRIO_PROCESS, 0, -10); setpriority(PRIO_PROCESS, 0, -10);
// Reset OMX subsystem — clears any stale encoder state from previous unclean exit
OMX_Deinit();
OMX_Init();
// Ensure base output directory exists // Ensure base output directory exists
mkdir(VIDEOS_BASE.c_str(), 0755); mkdir(VIDEOS_BASE.c_str(), 0755);
@@ -341,6 +345,16 @@ int main(int argc, char *argv[]) {
uint64_t ts = nanos_since_boot() - segment_start_ts; uint64_t ts = nanos_since_boot() - segment_start_ts;
// Validate buffer before encoding
if (buf->y == nullptr || buf->uv == nullptr || buf->width == 0 || buf->height == 0) {
LOGE("dashcamd: invalid frame buf y=%p uv=%p %zux%zu, skipping", buf->y, buf->uv, buf->width, buf->height);
continue;
}
if (frame_count == 0) {
LOGW("dashcamd: first encode w=%d h=%d stride=%d buf_y=%p buf_uv=%p", width, height, y_stride, buf->y, buf->uv);
}
// Feed NV12 frame directly to OMX encoder // Feed NV12 frame directly to OMX encoder
encoder->encode_frame_nv12(buf->y, y_stride, buf->uv, uv_stride, width, height, ts); encoder->encode_frame_nv12(buf->y, y_stride, buf->uv, uv_stride, width, height, ts);
frame_count++; frame_count++;

View File

@@ -446,6 +446,12 @@ OmxEncoder::OmxEncoder(const char* path, int width, int height, int fps, int bit
void OmxEncoder::handle_out_buf(OmxEncoder *e, OMX_BUFFERHEADERTYPE *out_buf) { void OmxEncoder::handle_out_buf(OmxEncoder *e, OMX_BUFFERHEADERTYPE *out_buf) {
int err; int err;
if (out_buf->pBuffer == nullptr || out_buf->nFilledLen == 0) {
OMX_CHECK(OMX_FillThisBuffer(e->handle, out_buf));
return;
}
uint8_t *buf_data = out_buf->pBuffer + out_buf->nOffset; uint8_t *buf_data = out_buf->pBuffer + out_buf->nOffset;
if (out_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { if (out_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
@@ -613,6 +619,7 @@ int OmxEncoder::encode_frame_nv12(const uint8_t *y_ptr, int y_stride, const uint
handle_out_buf(this, out_buf); handle_out_buf(this, out_buf);
} }
this->dirty = true; this->dirty = true;
this->counter++; this->counter++;

View File

@@ -263,6 +263,11 @@ static StatusWindow::StatusData collectStatus() {
// Telemetry // Telemetry
d.telemetry = readFile("/data/params/d/TelemetryEnabled"); d.telemetry = readFile("/data/params/d/TelemetryEnabled");
// Dashcam
QString dashcam_pid = shellCmd("pgrep -x dashcamd");
d.dashcam_status = dashcam_pid.isEmpty() ? "stopped" : "recording";
d.dashcam_size = shellCmd("du -sh /data/media/0/videos 2>/dev/null | awk '{print $1}'");
// Panda: checked on UI thread in applyResults() via scene.pandaType // Panda: checked on UI thread in applyResults() via scene.pandaType
return d; return d;
@@ -305,6 +310,7 @@ StatusWindow::StatusWindow(QWidget *parent) : QFrame(parent) {
vpn_label = makeRow("VPN"); vpn_label = makeRow("VPN");
gps_label = makeRow("GPS"); gps_label = makeRow("GPS");
telemetry_label = makeRow("Telemetry"); telemetry_label = makeRow("Telemetry");
dashcam_label = makeRow("Dashcam");
layout->addStretch(); layout->addStretch();
@@ -376,6 +382,16 @@ void StatusWindow::applyResults() {
telemetry_label->setText("Disabled"); telemetry_label->setText("Disabled");
telemetry_label->setStyleSheet("color: grey; font-size: 38px;"); telemetry_label->setStyleSheet("color: grey; font-size: 38px;");
} }
if (d.dashcam_status == "recording") {
QString text = "Recording";
if (!d.dashcam_size.isEmpty()) text += " (" + d.dashcam_size + ")";
dashcam_label->setText(text);
dashcam_label->setStyleSheet("color: #17c44d; font-size: 38px;");
} else {
dashcam_label->setText("Stopped");
dashcam_label->setStyleSheet("color: #ff4444; font-size: 38px;");
}
} }
void StatusWindow::mousePressEvent(QMouseEvent *e) { void StatusWindow::mousePressEvent(QMouseEvent *e) {

View File

@@ -20,6 +20,7 @@ public:
struct StatusData { struct StatusData {
QString time, storage, ram, load, temp, fan, ip, wifi; QString time, storage, ram, load, temp, fan, ip, wifi;
QString vpn_status, vpn_ip, gps, telemetry; QString vpn_status, vpn_ip, gps, telemetry;
QString dashcam_status, dashcam_size;
float temp_c = 0; float temp_c = 0;
}; };
@@ -49,6 +50,7 @@ private:
QLabel *gps_label; QLabel *gps_label;
QLabel *time_label; QLabel *time_label;
QLabel *telemetry_label; QLabel *telemetry_label;
QLabel *dashcam_label;
QLabel *panda_label; QLabel *panda_label;
}; };