fix: dashcamd OMX crash on restart, add dashcam status indicator
- 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:
Binary file not shown.
@@ -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++;
|
||||||
|
|||||||
@@ -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++;
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user