mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-19 01:53:57 +08:00
Encoderd: give every camera stream list of encoder streams (#28480)
* Compiles * fixed something * CLEANUP * todo * More cleanup * Add TODO * Update loggerd.cc * remove write here too
This commit is contained in:
@@ -5,9 +5,7 @@ VideoEncoder::~VideoEncoder() {}
|
||||
|
||||
void VideoEncoder::publisher_init() {
|
||||
// publish
|
||||
service_name = this->type == DriverCam ? "driverEncodeData" :
|
||||
(this->type == WideRoadCam ? "wideRoadEncodeData" :
|
||||
(this->in_width == this->out_width ? "roadEncodeData" : "qRoadEncodeData"));
|
||||
service_name = this->publish_name;
|
||||
pm.reset(new PubMaster({service_name}));
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
class VideoEncoder {
|
||||
public:
|
||||
VideoEncoder(const char* filename, CameraType type, int in_width, int in_height, int fps,
|
||||
int bitrate, cereal::EncodeIndex::Type codec, int out_width, int out_height)
|
||||
int bitrate, cereal::EncodeIndex::Type codec, int out_width, int out_height,
|
||||
const char* publish_name)
|
||||
: filename(filename), type(type), in_width(in_width), in_height(in_height), fps(fps),
|
||||
bitrate(bitrate), codec(codec), out_width(out_width), out_height(out_height) { }
|
||||
bitrate(bitrate), codec(codec), out_width(out_width), out_height(out_height),
|
||||
publish_name(publish_name) { }
|
||||
virtual ~VideoEncoder();
|
||||
virtual int encode_frame(VisionBuf* buf, VisionIpcBufExtra *extra) = 0;
|
||||
virtual void encoder_open(const char* path) = 0;
|
||||
@@ -28,6 +30,7 @@ public:
|
||||
|
||||
protected:
|
||||
const char* filename;
|
||||
const char* publish_name;
|
||||
int in_width, in_height;
|
||||
int out_width, out_height, fps;
|
||||
int bitrate;
|
||||
|
||||
@@ -17,8 +17,10 @@ extern "C" {
|
||||
class FfmpegEncoder : public VideoEncoder {
|
||||
public:
|
||||
FfmpegEncoder(const char* filename, CameraType type, int in_width, int in_height, int fps,
|
||||
int bitrate, cereal::EncodeIndex::Type codec, int out_width, int out_height) :
|
||||
VideoEncoder(filename, type, in_width, in_height, fps, bitrate, cereal::EncodeIndex::Type::BIG_BOX_LOSSLESS, out_width, out_height) { encoder_init(); }
|
||||
|
||||
int bitrate, cereal::EncodeIndex::Type codec, int out_width, int out_height,
|
||||
const char* publish_name) :
|
||||
VideoEncoder(filename, type, in_width, in_height, fps, bitrate, cereal::EncodeIndex::Type::BIG_BOX_LOSSLESS, out_width, out_height, publish_name) { encoder_init(); }
|
||||
~FfmpegEncoder();
|
||||
void encoder_init();
|
||||
int encode_frame(VisionBuf* buf, VisionIpcBufExtra *extra);
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
class V4LEncoder : public VideoEncoder {
|
||||
public:
|
||||
V4LEncoder(const char* filename, CameraType type, int in_width, int in_height, int fps,
|
||||
int bitrate, cereal::EncodeIndex::Type codec, int out_width, int out_height) :
|
||||
VideoEncoder(filename, type, in_width, in_height, fps, bitrate, codec, out_width, out_height) { encoder_init(); }
|
||||
int bitrate, cereal::EncodeIndex::Type codec, int out_width, int out_height, const char* publish_name) :
|
||||
VideoEncoder(filename, type, in_width, in_height, fps, bitrate, codec, out_width, out_height, publish_name) { encoder_init(); }
|
||||
~V4LEncoder();
|
||||
void encoder_init();
|
||||
int encode_frame(VisionBuf* buf, VisionIpcBufExtra *extra);
|
||||
|
||||
@@ -35,7 +35,7 @@ bool sync_encoders(EncoderdState *s, CameraType cam_type, uint32_t frame_id) {
|
||||
|
||||
|
||||
void encoder_thread(EncoderdState *s, const LogCameraInfo &cam_info) {
|
||||
util::set_thread_name(cam_info.filename);
|
||||
util::set_thread_name(cam_info.encoder_infos[0].filename);
|
||||
|
||||
std::vector<Encoder *> encoders;
|
||||
VisionIpcClient vipc_client = VisionIpcClient("camerad", cam_info.stream_type, false);
|
||||
@@ -50,20 +50,15 @@ void encoder_thread(EncoderdState *s, const LogCameraInfo &cam_info) {
|
||||
// init encoders
|
||||
if (encoders.empty()) {
|
||||
VisionBuf buf_info = vipc_client.buffers[0];
|
||||
LOGW("encoder %s init %dx%d", cam_info.filename, buf_info.width, buf_info.height);
|
||||
LOGW("encoder %s init %dx%d", cam_info.encoder_infos[0].filename, buf_info.width, buf_info.height);
|
||||
|
||||
if (buf_info.width > 0 && buf_info.height > 0) {
|
||||
// main encoder
|
||||
encoders.push_back(new Encoder(cam_info.filename, cam_info.type, buf_info.width, buf_info.height,
|
||||
cam_info.fps, cam_info.bitrate,
|
||||
cam_info.is_h265 ? cereal::EncodeIndex::Type::FULL_H_E_V_C : cereal::EncodeIndex::Type::QCAMERA_H264,
|
||||
buf_info.width, buf_info.height));
|
||||
// qcamera encoder
|
||||
if (cam_info.has_qcamera) {
|
||||
encoders.push_back(new Encoder(qcam_info.filename, cam_info.type, buf_info.width, buf_info.height,
|
||||
qcam_info.fps, qcam_info.bitrate,
|
||||
qcam_info.is_h265 ? cereal::EncodeIndex::Type::FULL_H_E_V_C : cereal::EncodeIndex::Type::QCAMERA_H264,
|
||||
qcam_info.frame_width, qcam_info.frame_height));
|
||||
for (const auto &encoder_info: cam_info.encoder_infos){
|
||||
encoders.push_back(new Encoder(encoder_info.filename, cam_info.type, buf_info.width, buf_info.height,
|
||||
encoder_info.fps, encoder_info.bitrate,
|
||||
encoder_info.encode_type,
|
||||
encoder_info.frame_width, encoder_info.frame_height,
|
||||
encoder_info.publish_name));
|
||||
}
|
||||
} else {
|
||||
LOGE("not initting empty encoder");
|
||||
@@ -85,7 +80,7 @@ void encoder_thread(EncoderdState *s, const LogCameraInfo &cam_info) {
|
||||
// detect loop around and drop the frames
|
||||
if (buf->get_frame_id() != extra.frame_id) {
|
||||
if (!lagging) {
|
||||
LOGE("encoder %s lag buffer id: %d extra id: %d", cam_info.filename, buf->get_frame_id(), extra.frame_id);
|
||||
LOGE("encoder %s lag buffer id: %d extra id: %d", cam_info.encoder_infos[0].filename, buf->get_frame_id(), extra.frame_id);
|
||||
lagging = true;
|
||||
}
|
||||
continue;
|
||||
|
||||
@@ -58,15 +58,13 @@ struct RemoteEncoder {
|
||||
bool seen_first_packet = false;
|
||||
};
|
||||
|
||||
int handle_encoder_msg(LoggerdState *s, Message *msg, std::string &name, struct RemoteEncoder &re) {
|
||||
const LogCameraInfo &cam_info = (name == "driverEncodeData") ? cameras_logged[1] :
|
||||
((name == "wideRoadEncodeData") ? cameras_logged[2] :
|
||||
((name == "qRoadEncodeData") ? qcam_info : cameras_logged[0]));
|
||||
int handle_encoder_msg(LoggerdState *s, Message *msg, std::string &name, struct RemoteEncoder &re, EncoderInfo encoder_info) {
|
||||
int bytes_count = 0;
|
||||
|
||||
// extract the message
|
||||
capnp::FlatArrayMessageReader cmsg(kj::ArrayPtr<capnp::word>((capnp::word *)msg->getData(), msg->getSize() / sizeof(capnp::word)));
|
||||
auto event = cmsg.getRoot<cereal::Event>();
|
||||
// TODO this should be dealt with generically
|
||||
auto edata = (name == "driverEncodeData") ? event.getDriverEncodeData() :
|
||||
((name == "wideRoadEncodeData") ? event.getWideRoadEncodeData() :
|
||||
((name == "qRoadEncodeData") ? event.getQRoadEncodeData() : event.getRoadEncodeData()));
|
||||
@@ -95,7 +93,7 @@ int handle_encoder_msg(LoggerdState *s, Message *msg, std::string &name, struct
|
||||
// we are in this segment now, process any queued messages before this one
|
||||
if (!re.q.empty()) {
|
||||
for (auto &qmsg: re.q) {
|
||||
bytes_count += handle_encoder_msg(s, qmsg, name, re);
|
||||
bytes_count += handle_encoder_msg(s, qmsg, name, re, encoder_info);
|
||||
}
|
||||
re.q.clear();
|
||||
}
|
||||
@@ -111,10 +109,10 @@ int handle_encoder_msg(LoggerdState *s, Message *msg, std::string &name, struct
|
||||
re.dropped_frames = 0;
|
||||
}
|
||||
// if we aren't actually recording, don't create the writer
|
||||
if (cam_info.record) {
|
||||
if (encoder_info.record) {
|
||||
re.writer.reset(new VideoWriter(s->segment_path,
|
||||
cam_info.filename, idx.getType() != cereal::EncodeIndex::Type::FULL_H_E_V_C,
|
||||
cam_info.frame_width, cam_info.frame_height, cam_info.fps, idx.getType()));
|
||||
encoder_info.filename, idx.getType() != cereal::EncodeIndex::Type::FULL_H_E_V_C,
|
||||
encoder_info.frame_width, encoder_info.frame_height, encoder_info.fps, idx.getType()));
|
||||
// write the header
|
||||
auto header = edata.getHeader();
|
||||
re.writer->write((uint8_t *)header.begin(), header.size(), idx.getTimestampEof()/1000, true, false);
|
||||
@@ -142,6 +140,7 @@ int handle_encoder_msg(LoggerdState *s, Message *msg, std::string &name, struct
|
||||
MessageBuilder bmsg;
|
||||
auto evt = bmsg.initEvent(event.getValid());
|
||||
evt.setLogMonoTime(event.getLogMonoTime());
|
||||
// TODO this should be dealt with generically
|
||||
if (name == "driverEncodeData") { evt.setDriverEncodeIdx(idx); }
|
||||
if (name == "wideRoadEncodeData") { evt.setWideRoadEncodeIdx(idx); }
|
||||
if (name == "qRoadEncodeData") { evt.setQRoadEncodeIdx(idx); }
|
||||
@@ -211,11 +210,12 @@ void loggerd_thread() {
|
||||
logger_rotate(&s);
|
||||
Params().put("CurrentRoute", s.logger.route_name);
|
||||
|
||||
// init encoders
|
||||
s.last_camera_seen_tms = millis_since_boot();
|
||||
std::map<std::string, EncoderInfo> encoder_infos_dict;
|
||||
for (const auto &cam : cameras_logged) {
|
||||
s.max_waiting++;
|
||||
if (cam.has_qcamera) { s.max_waiting++; }
|
||||
for (const auto &encoder_info: cam.encoder_infos) {
|
||||
encoder_infos_dict[encoder_info.publish_name] = encoder_info;
|
||||
s.max_waiting++;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t msg_count = 0, bytes_count = 0;
|
||||
@@ -234,7 +234,7 @@ void loggerd_thread() {
|
||||
|
||||
if (qs.encoder) {
|
||||
s.last_camera_seen_tms = millis_since_boot();
|
||||
bytes_count += handle_encoder_msg(&s, msg, qs.name, remote_encoders[sock]);
|
||||
bytes_count += handle_encoder_msg(&s, msg, qs.name, remote_encoders[sock], encoder_infos_dict[qs.name]);
|
||||
} else {
|
||||
logger_log(&s.logger, (uint8_t *)msg->getData(), msg->getSize(), in_qlog);
|
||||
bytes_count += msg->getSize();
|
||||
|
||||
@@ -42,62 +42,67 @@ const int DCAM_BITRATE = MAIN_BITRATE;
|
||||
const bool LOGGERD_TEST = getenv("LOGGERD_TEST");
|
||||
const int SEGMENT_LENGTH = LOGGERD_TEST ? atoi(getenv("LOGGERD_SEGMENT_LENGTH")) : 60;
|
||||
|
||||
struct LogCameraInfo {
|
||||
CameraType type;
|
||||
class EncoderInfo {
|
||||
public:
|
||||
const char *publish_name;
|
||||
const char *filename;
|
||||
VisionStreamType stream_type;
|
||||
int frame_width, frame_height;
|
||||
int fps;
|
||||
int bitrate;
|
||||
bool is_h265;
|
||||
bool has_qcamera;
|
||||
bool record;
|
||||
bool record = true;
|
||||
int frame_width = 1928;
|
||||
int frame_height = 1208;
|
||||
int fps = MAIN_FPS;
|
||||
int bitrate = MAIN_BITRATE;
|
||||
cereal::EncodeIndex::Type encode_type = cereal::EncodeIndex::Type::FULL_H_E_V_C;
|
||||
};
|
||||
|
||||
const LogCameraInfo cameras_logged[] = {
|
||||
{
|
||||
.type = RoadCam,
|
||||
.stream_type = VISION_STREAM_ROAD,
|
||||
.filename = "fcamera.hevc",
|
||||
.fps = MAIN_FPS,
|
||||
.bitrate = MAIN_BITRATE,
|
||||
.is_h265 = true,
|
||||
.has_qcamera = true,
|
||||
.record = true,
|
||||
.frame_width = 1928,
|
||||
.frame_height = 1208,
|
||||
},
|
||||
{
|
||||
.type = DriverCam,
|
||||
.stream_type = VISION_STREAM_DRIVER,
|
||||
.filename = "dcamera.hevc",
|
||||
.fps = MAIN_FPS,
|
||||
.bitrate = DCAM_BITRATE,
|
||||
.is_h265 = true,
|
||||
.has_qcamera = false,
|
||||
.record = Params().getBool("RecordFront"),
|
||||
.frame_width = 1928,
|
||||
.frame_height = 1208,
|
||||
},
|
||||
{
|
||||
.type = WideRoadCam,
|
||||
.stream_type = VISION_STREAM_WIDE_ROAD,
|
||||
.filename = "ecamera.hevc",
|
||||
.fps = MAIN_FPS,
|
||||
.bitrate = MAIN_BITRATE,
|
||||
.is_h265 = true,
|
||||
.has_qcamera = false,
|
||||
.record = true,
|
||||
.frame_width = 1928,
|
||||
.frame_height = 1208,
|
||||
},
|
||||
class LogCameraInfo {
|
||||
public:
|
||||
int fps = MAIN_FPS;
|
||||
CameraType type;
|
||||
VisionStreamType stream_type;
|
||||
std::vector<EncoderInfo> encoder_infos;
|
||||
};
|
||||
const LogCameraInfo qcam_info = {
|
||||
|
||||
const EncoderInfo main_road_encoder_info = {
|
||||
.publish_name = "roadEncodeData",
|
||||
.filename = "fcamera.hevc",
|
||||
};
|
||||
const EncoderInfo main_wide_road_encoder_info = {
|
||||
.publish_name = "wideRoadEncodeData",
|
||||
.filename = "ecamera.hevc",
|
||||
};
|
||||
const EncoderInfo main_driver_encoder_info = {
|
||||
.publish_name = "driverEncodeData",
|
||||
.filename = "dcamera.hevc",
|
||||
.record = Params().getBool("RecordFront"),
|
||||
};
|
||||
|
||||
const EncoderInfo qcam_encoder_info = {
|
||||
.publish_name = "qRoadEncodeData",
|
||||
.filename = "qcamera.ts",
|
||||
.fps = MAIN_FPS,
|
||||
.bitrate = 256000,
|
||||
.is_h265 = false,
|
||||
.record = true,
|
||||
.encode_type = cereal::EncodeIndex::Type::QCAMERA_H264,
|
||||
.frame_width = 526,
|
||||
.frame_height = 330,
|
||||
};
|
||||
|
||||
|
||||
const LogCameraInfo road_camera_info{
|
||||
.type = RoadCam,
|
||||
.stream_type = VISION_STREAM_ROAD,
|
||||
.encoder_infos = {main_road_encoder_info, qcam_encoder_info}
|
||||
};
|
||||
|
||||
const LogCameraInfo wide_road_camera_info{
|
||||
.type = WideRoadCam,
|
||||
.stream_type = VISION_STREAM_WIDE_ROAD,
|
||||
.encoder_infos = {main_wide_road_encoder_info}
|
||||
};
|
||||
|
||||
const LogCameraInfo driver_camera_info{
|
||||
.type = DriverCam,
|
||||
.stream_type = VISION_STREAM_DRIVER,
|
||||
.encoder_infos = {main_driver_encoder_info}
|
||||
};
|
||||
|
||||
const LogCameraInfo cameras_logged[] = {road_camera_info, wide_road_camera_info, driver_camera_info};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user